aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-02-20 13:39:02 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-20 13:39:02 -0500
commita38bbe7d57b1d4d86e90823dd85d7883ae23be1d (patch)
treea2946ea73c8b92a701f4ee93e8dc3cc6a829bd1c
parentb99fe0e28fe0ba7d6e17e234e1150f1d9e197632 (diff)
parent7f47b19bd744c7945ad554fc00665fdbd13794bc (diff)
Merge branch 'net-Expose-KVD-linear-parts-as-resources'
Jiri Pirko says: ==================== net: Expose KVD linear parts as resources Arkadi says: Expose the KVD linear partitions via the devlink resource interface. This will give the user the ability to control the linear memory division. --- v1->v2: - patch1: - fixed u64 division error reported by kbuildbot ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c87
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c187
-rw-r--r--include/net/devlink.h4
-rw-r--r--net/core/devlink.c32
5 files changed, 220 insertions, 97 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 5e8ea712caa2..bfde93910f82 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3798,70 +3798,6 @@ static const struct mlxsw_config_profile mlxsw_sp_config_profile = {
3798 .resource_query_enable = 1, 3798 .resource_query_enable = 1,
3799}; 3799};
3800 3800
3801static bool
3802mlxsw_sp_resource_kvd_granularity_validate(struct netlink_ext_ack *extack,
3803 u64 size)
3804{
3805 const struct mlxsw_config_profile *profile;
3806
3807 profile = &mlxsw_sp_config_profile;
3808 if (size % profile->kvd_hash_granularity) {
3809 NL_SET_ERR_MSG_MOD(extack, "resource set with wrong granularity");
3810 return false;
3811 }
3812 return true;
3813}
3814
3815static int
3816mlxsw_sp_resource_kvd_size_validate(struct devlink *devlink, u64 size,
3817 struct netlink_ext_ack *extack)
3818{
3819 NL_SET_ERR_MSG_MOD(extack, "kvd size cannot be changed");
3820 return -EINVAL;
3821}
3822
3823static int
3824mlxsw_sp_resource_kvd_linear_size_validate(struct devlink *devlink, u64 size,
3825 struct netlink_ext_ack *extack)
3826{
3827 if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size))
3828 return -EINVAL;
3829
3830 return 0;
3831}
3832
3833static int
3834mlxsw_sp_resource_kvd_hash_single_size_validate(struct devlink *devlink, u64 size,
3835 struct netlink_ext_ack *extack)
3836{
3837 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
3838
3839 if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size))
3840 return -EINVAL;
3841
3842 if (size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE)) {
3843 NL_SET_ERR_MSG_MOD(extack, "hash single size is smaller than minimum");
3844 return -EINVAL;
3845 }
3846 return 0;
3847}
3848
3849static int
3850mlxsw_sp_resource_kvd_hash_double_size_validate(struct devlink *devlink, u64 size,
3851 struct netlink_ext_ack *extack)
3852{
3853 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
3854
3855 if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size))
3856 return -EINVAL;
3857
3858 if (size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE)) {
3859 NL_SET_ERR_MSG_MOD(extack, "hash double size is smaller than minimum");
3860 return -EINVAL;
3861 }
3862 return 0;
3863}
3864
3865static u64 mlxsw_sp_resource_kvd_linear_occ_get(struct devlink *devlink) 3801static u64 mlxsw_sp_resource_kvd_linear_occ_get(struct devlink *devlink)
3866{ 3802{
3867 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 3803 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
@@ -3870,23 +3806,10 @@ static u64 mlxsw_sp_resource_kvd_linear_occ_get(struct devlink *devlink)
3870 return mlxsw_sp_kvdl_occ_get(mlxsw_sp); 3806 return mlxsw_sp_kvdl_occ_get(mlxsw_sp);
3871} 3807}
3872 3808
3873static struct devlink_resource_ops mlxsw_sp_resource_kvd_ops = {
3874 .size_validate = mlxsw_sp_resource_kvd_size_validate,
3875};
3876
3877static struct devlink_resource_ops mlxsw_sp_resource_kvd_linear_ops = { 3809static struct devlink_resource_ops mlxsw_sp_resource_kvd_linear_ops = {
3878 .size_validate = mlxsw_sp_resource_kvd_linear_size_validate,
3879 .occ_get = mlxsw_sp_resource_kvd_linear_occ_get, 3810 .occ_get = mlxsw_sp_resource_kvd_linear_occ_get,
3880}; 3811};
3881 3812
3882static struct devlink_resource_ops mlxsw_sp_resource_kvd_hash_single_ops = {
3883 .size_validate = mlxsw_sp_resource_kvd_hash_single_size_validate,
3884};
3885
3886static struct devlink_resource_ops mlxsw_sp_resource_kvd_hash_double_ops = {
3887 .size_validate = mlxsw_sp_resource_kvd_hash_double_size_validate,
3888};
3889
3890static struct devlink_resource_size_params mlxsw_sp_kvd_size_params; 3813static struct devlink_resource_size_params mlxsw_sp_kvd_size_params;
3891static struct devlink_resource_size_params mlxsw_sp_linear_size_params; 3814static struct devlink_resource_size_params mlxsw_sp_linear_size_params;
3892static struct devlink_resource_size_params mlxsw_sp_hash_single_size_params; 3815static struct devlink_resource_size_params mlxsw_sp_hash_single_size_params;
@@ -3948,7 +3871,7 @@ static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core)
3948 MLXSW_SP_RESOURCE_KVD, 3871 MLXSW_SP_RESOURCE_KVD,
3949 DEVLINK_RESOURCE_ID_PARENT_TOP, 3872 DEVLINK_RESOURCE_ID_PARENT_TOP,
3950 &mlxsw_sp_kvd_size_params, 3873 &mlxsw_sp_kvd_size_params,
3951 &mlxsw_sp_resource_kvd_ops); 3874 NULL);
3952 if (err) 3875 if (err)
3953 return err; 3876 return err;
3954 3877
@@ -3962,6 +3885,10 @@ static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core)
3962 if (err) 3885 if (err)
3963 return err; 3886 return err;
3964 3887
3888 err = mlxsw_sp_kvdl_resources_register(devlink);
3889 if (err)
3890 return err;
3891
3965 double_size = kvd_size - linear_size; 3892 double_size = kvd_size - linear_size;
3966 double_size *= profile->kvd_hash_double_parts; 3893 double_size *= profile->kvd_hash_double_parts;
3967 double_size /= profile->kvd_hash_double_parts + 3894 double_size /= profile->kvd_hash_double_parts +
@@ -3972,7 +3899,7 @@ static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core)
3972 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE, 3899 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
3973 MLXSW_SP_RESOURCE_KVD, 3900 MLXSW_SP_RESOURCE_KVD,
3974 &mlxsw_sp_hash_double_size_params, 3901 &mlxsw_sp_hash_double_size_params,
3975 &mlxsw_sp_resource_kvd_hash_double_ops); 3902 NULL);
3976 if (err) 3903 if (err)
3977 return err; 3904 return err;
3978 3905
@@ -3982,7 +3909,7 @@ static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core)
3982 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, 3909 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
3983 MLXSW_SP_RESOURCE_KVD, 3910 MLXSW_SP_RESOURCE_KVD,
3984 &mlxsw_sp_hash_single_size_params, 3911 &mlxsw_sp_hash_single_size_params,
3985 &mlxsw_sp_resource_kvd_hash_single_ops); 3912 NULL);
3986 if (err) 3913 if (err)
3987 return err; 3914 return err;
3988 3915
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 6718a1f0482c..675e03a892ed 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -70,12 +70,18 @@
70#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR "linear" 70#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR "linear"
71#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE "hash_single" 71#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE "hash_single"
72#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE "hash_double" 72#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE "hash_double"
73#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_SINGLES "singles"
74#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_CHUNKS "chunks"
75#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_LARGE_CHUNKS "large_chunks"
73 76
74enum mlxsw_sp_resource_id { 77enum mlxsw_sp_resource_id {
75 MLXSW_SP_RESOURCE_KVD, 78 MLXSW_SP_RESOURCE_KVD,
76 MLXSW_SP_RESOURCE_KVD_LINEAR, 79 MLXSW_SP_RESOURCE_KVD_LINEAR,
77 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, 80 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
78 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE, 81 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
82 MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
83 MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
84 MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
79}; 85};
80 86
81struct mlxsw_sp_port; 87struct mlxsw_sp_port;
@@ -433,6 +439,7 @@ int mlxsw_sp_kvdl_alloc_size_query(struct mlxsw_sp *mlxsw_sp,
433 unsigned int entry_count, 439 unsigned int entry_count,
434 unsigned int *p_alloc_size); 440 unsigned int *p_alloc_size);
435u64 mlxsw_sp_kvdl_occ_get(const struct mlxsw_sp *mlxsw_sp); 441u64 mlxsw_sp_kvdl_occ_get(const struct mlxsw_sp *mlxsw_sp);
442int mlxsw_sp_kvdl_resources_register(struct devlink *devlink);
436 443
437struct mlxsw_sp_acl_rule_info { 444struct mlxsw_sp_acl_rule_info {
438 unsigned int priority; 445 unsigned int priority;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
index 55f9d2d70f9e..d27fa57ad3c3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
@@ -67,7 +67,7 @@ struct mlxsw_sp_kvdl_part_info {
67 67
68struct mlxsw_sp_kvdl_part { 68struct mlxsw_sp_kvdl_part {
69 struct list_head list; 69 struct list_head list;
70 const struct mlxsw_sp_kvdl_part_info *info; 70 struct mlxsw_sp_kvdl_part_info *info;
71 unsigned long usage[0]; /* Entries */ 71 unsigned long usage[0]; /* Entries */
72}; 72};
73 73
@@ -188,21 +188,27 @@ int mlxsw_sp_kvdl_alloc_size_query(struct mlxsw_sp *mlxsw_sp,
188 return 0; 188 return 0;
189} 189}
190 190
191enum mlxsw_sp_kvdl_part_id {
192 MLXSW_SP_KVDL_PART_SINGLE,
193 MLXSW_SP_KVDL_PART_CHUNKS,
194 MLXSW_SP_KVDL_PART_LARGE_CHUNKS,
195};
196
191static const struct mlxsw_sp_kvdl_part_info kvdl_parts_info[] = { 197static const struct mlxsw_sp_kvdl_part_info kvdl_parts_info[] = {
192 { 198 {
193 .part_index = 0, 199 .part_index = MLXSW_SP_KVDL_PART_SINGLE,
194 .start_index = MLXSW_SP_KVDL_SINGLE_BASE, 200 .start_index = MLXSW_SP_KVDL_SINGLE_BASE,
195 .end_index = MLXSW_SP_KVDL_SINGLE_END, 201 .end_index = MLXSW_SP_KVDL_SINGLE_END,
196 .alloc_size = 1, 202 .alloc_size = 1,
197 }, 203 },
198 { 204 {
199 .part_index = 1, 205 .part_index = MLXSW_SP_KVDL_PART_CHUNKS,
200 .start_index = MLXSW_SP_KVDL_CHUNKS_BASE, 206 .start_index = MLXSW_SP_KVDL_CHUNKS_BASE,
201 .end_index = MLXSW_SP_KVDL_CHUNKS_END, 207 .end_index = MLXSW_SP_KVDL_CHUNKS_END,
202 .alloc_size = MLXSW_SP_CHUNK_MAX, 208 .alloc_size = MLXSW_SP_CHUNK_MAX,
203 }, 209 },
204 { 210 {
205 .part_index = 2, 211 .part_index = MLXSW_SP_KVDL_PART_LARGE_CHUNKS,
206 .start_index = MLXSW_SP_KVDL_LARGE_CHUNKS_BASE, 212 .start_index = MLXSW_SP_KVDL_LARGE_CHUNKS_BASE,
207 .end_index = MLXSW_SP_KVDL_LARGE_CHUNKS_END, 213 .end_index = MLXSW_SP_KVDL_LARGE_CHUNKS_END,
208 .alloc_size = MLXSW_SP_LARGE_CHUNK_MAX, 214 .alloc_size = MLXSW_SP_LARGE_CHUNK_MAX,
@@ -222,27 +228,74 @@ mlxsw_sp_kvdl_part_find(struct mlxsw_sp *mlxsw_sp, unsigned int part_index)
222 return NULL; 228 return NULL;
223} 229}
224 230
231static void
232mlxsw_sp_kvdl_part_update(struct mlxsw_sp *mlxsw_sp,
233 struct mlxsw_sp_kvdl_part *part, unsigned int size)
234{
235 struct mlxsw_sp_kvdl_part_info *info = part->info;
236
237 if (list_is_last(&part->list, &mlxsw_sp->kvdl->parts_list)) {
238 info->end_index = size - 1;
239 } else {
240 struct mlxsw_sp_kvdl_part *last_part;
241
242 last_part = list_next_entry(part, list);
243 info->start_index = last_part->info->end_index + 1;
244 info->end_index = info->start_index + size - 1;
245 }
246}
247
225static int mlxsw_sp_kvdl_part_init(struct mlxsw_sp *mlxsw_sp, 248static int mlxsw_sp_kvdl_part_init(struct mlxsw_sp *mlxsw_sp,
226 unsigned int part_index) 249 unsigned int part_index)
227{ 250{
251 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
228 const struct mlxsw_sp_kvdl_part_info *info; 252 const struct mlxsw_sp_kvdl_part_info *info;
253 enum mlxsw_sp_resource_id resource_id;
229 struct mlxsw_sp_kvdl_part *part; 254 struct mlxsw_sp_kvdl_part *part;
255 bool need_update = true;
230 unsigned int nr_entries; 256 unsigned int nr_entries;
231 size_t usage_size; 257 size_t usage_size;
258 u64 resource_size;
259 int err;
232 260
233 info = &kvdl_parts_info[part_index]; 261 info = &kvdl_parts_info[part_index];
234 262
235 nr_entries = (info->end_index - info->start_index + 1) / 263 switch (part_index) {
236 info->alloc_size; 264 case MLXSW_SP_KVDL_PART_SINGLE:
265 resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE;
266 break;
267 case MLXSW_SP_KVDL_PART_CHUNKS:
268 resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS;
269 break;
270 case MLXSW_SP_KVDL_PART_LARGE_CHUNKS:
271 resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS;
272 break;
273 }
274
275 err = devlink_resource_size_get(devlink, resource_id, &resource_size);
276 if (err) {
277 need_update = false;
278 resource_size = info->end_index - info->start_index + 1;
279 }
280
281 nr_entries = resource_size / info->alloc_size;
237 usage_size = BITS_TO_LONGS(nr_entries) * sizeof(unsigned long); 282 usage_size = BITS_TO_LONGS(nr_entries) * sizeof(unsigned long);
238 part = kzalloc(sizeof(*part) + usage_size, GFP_KERNEL); 283 part = kzalloc(sizeof(*part) + usage_size, GFP_KERNEL);
239 if (!part) 284 if (!part)
240 return -ENOMEM; 285 return -ENOMEM;
241 286
242 part->info = info; 287 part->info = kmemdup(info, sizeof(*part->info), GFP_KERNEL);
243 list_add(&part->list, &mlxsw_sp->kvdl->parts_list); 288 if (!part->info)
289 goto err_part_info_alloc;
244 290
291 list_add(&part->list, &mlxsw_sp->kvdl->parts_list);
292 if (need_update)
293 mlxsw_sp_kvdl_part_update(mlxsw_sp, part, resource_size);
245 return 0; 294 return 0;
295
296err_part_info_alloc:
297 kfree(part);
298 return -ENOMEM;
246} 299}
247 300
248static void mlxsw_sp_kvdl_part_fini(struct mlxsw_sp *mlxsw_sp, 301static void mlxsw_sp_kvdl_part_fini(struct mlxsw_sp *mlxsw_sp,
@@ -255,6 +308,7 @@ static void mlxsw_sp_kvdl_part_fini(struct mlxsw_sp *mlxsw_sp,
255 return; 308 return;
256 309
257 list_del(&part->list); 310 list_del(&part->list);
311 kfree(part->info);
258 kfree(part); 312 kfree(part);
259} 313}
260 314
@@ -312,6 +366,123 @@ u64 mlxsw_sp_kvdl_occ_get(const struct mlxsw_sp *mlxsw_sp)
312 return occ; 366 return occ;
313} 367}
314 368
369u64 mlxsw_sp_kvdl_single_occ_get(struct devlink *devlink)
370{
371 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
372 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
373 struct mlxsw_sp_kvdl_part *part;
374
375 part = mlxsw_sp_kvdl_part_find(mlxsw_sp, MLXSW_SP_KVDL_PART_SINGLE);
376 if (!part)
377 return -EINVAL;
378
379 return mlxsw_sp_kvdl_part_occ(part);
380}
381
382u64 mlxsw_sp_kvdl_chunks_occ_get(struct devlink *devlink)
383{
384 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
385 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
386 struct mlxsw_sp_kvdl_part *part;
387
388 part = mlxsw_sp_kvdl_part_find(mlxsw_sp, MLXSW_SP_KVDL_PART_CHUNKS);
389 if (!part)
390 return -EINVAL;
391
392 return mlxsw_sp_kvdl_part_occ(part);
393}
394
395u64 mlxsw_sp_kvdl_large_chunks_occ_get(struct devlink *devlink)
396{
397 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
398 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
399 struct mlxsw_sp_kvdl_part *part;
400
401 part = mlxsw_sp_kvdl_part_find(mlxsw_sp,
402 MLXSW_SP_KVDL_PART_LARGE_CHUNKS);
403 if (!part)
404 return -EINVAL;
405
406 return mlxsw_sp_kvdl_part_occ(part);
407}
408
409static struct devlink_resource_ops mlxsw_sp_kvdl_single_ops = {
410 .occ_get = mlxsw_sp_kvdl_single_occ_get,
411};
412
413static struct devlink_resource_ops mlxsw_sp_kvdl_chunks_ops = {
414 .occ_get = mlxsw_sp_kvdl_chunks_occ_get,
415};
416
417static struct devlink_resource_ops mlxsw_sp_kvdl_chunks_large_ops = {
418 .occ_get = mlxsw_sp_kvdl_large_chunks_occ_get,
419};
420
421static struct devlink_resource_size_params mlxsw_sp_kvdl_single_size_params = {
422 .size_min = 0,
423 .size_granularity = 1,
424 .unit = DEVLINK_RESOURCE_UNIT_ENTRY,
425};
426
427static struct devlink_resource_size_params mlxsw_sp_kvdl_chunks_size_params = {
428 .size_min = 0,
429 .size_granularity = MLXSW_SP_CHUNK_MAX,
430 .unit = DEVLINK_RESOURCE_UNIT_ENTRY,
431};
432
433static struct devlink_resource_size_params mlxsw_sp_kvdl_large_chunks_size_params = {
434 .size_min = 0,
435 .size_granularity = MLXSW_SP_LARGE_CHUNK_MAX,
436 .unit = DEVLINK_RESOURCE_UNIT_ENTRY,
437};
438
439static void
440mlxsw_sp_kvdl_resource_size_params_prepare(struct devlink *devlink)
441{
442 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
443 u32 kvdl_max_size;
444
445 kvdl_max_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
446 MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE) -
447 MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE);
448
449 mlxsw_sp_kvdl_single_size_params.size_max = kvdl_max_size;
450 mlxsw_sp_kvdl_chunks_size_params.size_max = kvdl_max_size;
451 mlxsw_sp_kvdl_large_chunks_size_params.size_max = kvdl_max_size;
452}
453
454int mlxsw_sp_kvdl_resources_register(struct devlink *devlink)
455{
456 int err;
457
458 mlxsw_sp_kvdl_resource_size_params_prepare(devlink);
459 err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_SINGLES,
460 false, MLXSW_SP_KVDL_SINGLE_SIZE,
461 MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
462 MLXSW_SP_RESOURCE_KVD_LINEAR,
463 &mlxsw_sp_kvdl_single_size_params,
464 &mlxsw_sp_kvdl_single_ops);
465 if (err)
466 return err;
467
468 err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_CHUNKS,
469 false, MLXSW_SP_KVDL_CHUNKS_SIZE,
470 MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
471 MLXSW_SP_RESOURCE_KVD_LINEAR,
472 &mlxsw_sp_kvdl_chunks_size_params,
473 &mlxsw_sp_kvdl_chunks_ops);
474 if (err)
475 return err;
476
477 err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_LARGE_CHUNKS,
478 false, MLXSW_SP_KVDL_LARGE_CHUNKS_SIZE,
479 MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
480 MLXSW_SP_RESOURCE_KVD_LINEAR,
481 &mlxsw_sp_kvdl_large_chunks_size_params,
482 &mlxsw_sp_kvdl_chunks_large_ops);
483 return err;
484}
485
315int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp) 486int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
316{ 487{
317 struct mlxsw_sp_kvdl *kvdl; 488 struct mlxsw_sp_kvdl *kvdl;
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 6545b03e97f7..8d1c3f276dea 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -234,13 +234,9 @@ struct devlink_dpipe_headers {
234/** 234/**
235 * struct devlink_resource_ops - resource ops 235 * struct devlink_resource_ops - resource ops
236 * @occ_get: get the occupied size 236 * @occ_get: get the occupied size
237 * @size_validate: validate the size of the resource before update, reload
238 * is needed for changes to take place
239 */ 237 */
240struct devlink_resource_ops { 238struct devlink_resource_ops {
241 u64 (*occ_get)(struct devlink *devlink); 239 u64 (*occ_get)(struct devlink *devlink);
242 int (*size_validate)(struct devlink *devlink, u64 size,
243 struct netlink_ext_ack *extack);
244}; 240};
245 241
246/** 242/**
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 18d385ed8237..88e846779269 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2338,6 +2338,32 @@ out:
2338 resource->size_valid = size_valid; 2338 resource->size_valid = size_valid;
2339} 2339}
2340 2340
2341static int
2342devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2343 struct netlink_ext_ack *extack)
2344{
2345 u64 reminder;
2346 int err = 0;
2347
2348 if (size > resource->size_params->size_max) {
2349 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2350 err = -EINVAL;
2351 }
2352
2353 if (size < resource->size_params->size_min) {
2354 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2355 err = -EINVAL;
2356 }
2357
2358 div64_u64_rem(size, resource->size_params->size_granularity, &reminder);
2359 if (reminder) {
2360 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2361 err = -EINVAL;
2362 }
2363
2364 return err;
2365}
2366
2341static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2367static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2342 struct genl_info *info) 2368 struct genl_info *info)
2343{ 2369{
@@ -2356,12 +2382,8 @@ static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2356 if (!resource) 2382 if (!resource)
2357 return -EINVAL; 2383 return -EINVAL;
2358 2384
2359 if (!resource->resource_ops->size_validate)
2360 return -EINVAL;
2361
2362 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2385 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2363 err = resource->resource_ops->size_validate(devlink, size, 2386 err = devlink_resource_validate_size(resource, size, info->extack);
2364 info->extack);
2365 if (err) 2387 if (err)
2366 return err; 2388 return err;
2367 2389