Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 887839e6 authored by Arkadi Sharshevsky's avatar Arkadi Sharshevsky Committed by David S. Miller
Browse files

mlxsw: spectrum_kvdl: Add support for dynamic partition set



Add support for dynamic partition set via the resource interface.

Signed-off-by: default avatarArkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51d3c08e
Loading
Loading
Loading
Loading
+53 −5
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ struct mlxsw_sp_kvdl_part_info {

struct mlxsw_sp_kvdl_part {
	struct list_head list;
	const struct mlxsw_sp_kvdl_part_info *info;
	struct mlxsw_sp_kvdl_part_info *info;
	unsigned long usage[0];	/* Entries */
};

@@ -228,27 +228,74 @@ mlxsw_sp_kvdl_part_find(struct mlxsw_sp *mlxsw_sp, unsigned int part_index)
	return NULL;
}

static void
mlxsw_sp_kvdl_part_update(struct mlxsw_sp *mlxsw_sp,
			  struct mlxsw_sp_kvdl_part *part, unsigned int size)
{
	struct mlxsw_sp_kvdl_part_info *info = part->info;

	if (list_is_last(&part->list, &mlxsw_sp->kvdl->parts_list)) {
		info->end_index = size - 1;
	} else  {
		struct mlxsw_sp_kvdl_part *last_part;

		last_part = list_next_entry(part, list);
		info->start_index = last_part->info->end_index + 1;
		info->end_index = info->start_index + size - 1;
	}
}

static int mlxsw_sp_kvdl_part_init(struct mlxsw_sp *mlxsw_sp,
				   unsigned int part_index)
{
	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
	const struct mlxsw_sp_kvdl_part_info *info;
	enum mlxsw_sp_resource_id resource_id;
	struct mlxsw_sp_kvdl_part *part;
	bool need_update = true;
	unsigned int nr_entries;
	size_t usage_size;
	u64 resource_size;
	int err;

	info = &kvdl_parts_info[part_index];

	nr_entries = (info->end_index - info->start_index + 1) /
		     info->alloc_size;
	switch (part_index) {
	case MLXSW_SP_KVDL_PART_SINGLE:
		resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE;
		break;
	case MLXSW_SP_KVDL_PART_CHUNKS:
		resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS;
		break;
	case MLXSW_SP_KVDL_PART_LARGE_CHUNKS:
		resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS;
		break;
	}

	err = devlink_resource_size_get(devlink, resource_id, &resource_size);
	if (err) {
		need_update = false;
		resource_size = info->end_index - info->start_index + 1;
	}

	nr_entries = resource_size / info->alloc_size;
	usage_size = BITS_TO_LONGS(nr_entries) * sizeof(unsigned long);
	part = kzalloc(sizeof(*part) + usage_size, GFP_KERNEL);
	if (!part)
		return -ENOMEM;

	part->info = info;
	list_add(&part->list, &mlxsw_sp->kvdl->parts_list);
	part->info = kmemdup(info, sizeof(*part->info), GFP_KERNEL);
	if (!part->info)
		goto err_part_info_alloc;

	list_add(&part->list, &mlxsw_sp->kvdl->parts_list);
	if (need_update)
		mlxsw_sp_kvdl_part_update(mlxsw_sp, part, resource_size);
	return 0;

err_part_info_alloc:
	kfree(part);
	return -ENOMEM;
}

static void mlxsw_sp_kvdl_part_fini(struct mlxsw_sp *mlxsw_sp,
@@ -261,6 +308,7 @@ static void mlxsw_sp_kvdl_part_fini(struct mlxsw_sp *mlxsw_sp,
		return;

	list_del(&part->list);
	kfree(part->info);
	kfree(part);
}