aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoshe Shemesh <moshe@mellanox.com>2018-07-04 07:30:28 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-05 06:58:35 -0400
commiteabaef1896bc06319461a644e3aa139885454def (patch)
tree4c9c68e3a8fb3356577984812a785befe7c0a901
parent827ad90cfa6140f86c398a7a8d32d9f319835273 (diff)
devlink: Add devlink_param register and unregister
Define configuration parameters data structure. Add functions to register and unregister the driver supported configuration parameters table. For each parameter registered, the driver should fill all the parameter's fields. In case the only supported configuration mode is "driverinit" the parameter's get()/set() functions are not required and should be set to NULL, for any other configuration mode, these functions are required and should be set by the driver. Signed-off-by: Moshe Shemesh <moshe@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/devlink.h85
-rw-r--r--include/uapi/linux/devlink.h10
-rw-r--r--net/core/devlink.c148
3 files changed, 243 insertions, 0 deletions
diff --git a/include/net/devlink.h b/include/net/devlink.h
index e336ea9c73df..4a0687a1fb99 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -27,6 +27,7 @@ struct devlink {
27 struct list_head sb_list; 27 struct list_head sb_list;
28 struct list_head dpipe_table_list; 28 struct list_head dpipe_table_list;
29 struct list_head resource_list; 29 struct list_head resource_list;
30 struct list_head param_list;
30 struct devlink_dpipe_headers *dpipe_headers; 31 struct devlink_dpipe_headers *dpipe_headers;
31 const struct devlink_ops *ops; 32 const struct devlink_ops *ops;
32 struct device *dev; 33 struct device *dev;
@@ -295,6 +296,68 @@ struct devlink_resource {
295 296
296#define DEVLINK_RESOURCE_ID_PARENT_TOP 0 297#define DEVLINK_RESOURCE_ID_PARENT_TOP 0
297 298
299#define DEVLINK_PARAM_MAX_STRING_VALUE 32
300enum devlink_param_type {
301 DEVLINK_PARAM_TYPE_U8,
302 DEVLINK_PARAM_TYPE_U16,
303 DEVLINK_PARAM_TYPE_U32,
304 DEVLINK_PARAM_TYPE_STRING,
305 DEVLINK_PARAM_TYPE_BOOL,
306};
307
308union devlink_param_value {
309 u8 vu8;
310 u16 vu16;
311 u32 vu32;
312 const char *vstr;
313 bool vbool;
314};
315
316struct devlink_param_gset_ctx {
317 union devlink_param_value val;
318 enum devlink_param_cmode cmode;
319};
320
321/**
322 * struct devlink_param - devlink configuration parameter data
323 * @name: name of the parameter
324 * @generic: indicates if the parameter is generic or driver specific
325 * @type: parameter type
326 * @supported_cmodes: bitmap of supported configuration modes
327 * @get: get parameter value, used for runtime and permanent
328 * configuration modes
329 * @set: set parameter value, used for runtime and permanent
330 * configuration modes
331 *
332 * This struct should be used by the driver to fill the data for
333 * a parameter it registers.
334 */
335struct devlink_param {
336 u32 id;
337 const char *name;
338 bool generic;
339 enum devlink_param_type type;
340 unsigned long supported_cmodes;
341 int (*get)(struct devlink *devlink, u32 id,
342 struct devlink_param_gset_ctx *ctx);
343 int (*set)(struct devlink *devlink, u32 id,
344 struct devlink_param_gset_ctx *ctx);
345};
346
347struct devlink_param_item {
348 struct list_head list;
349 const struct devlink_param *param;
350 union devlink_param_value driverinit_value;
351 bool driverinit_value_valid;
352};
353
354enum devlink_param_generic_id {
355
356 /* add new param generic ids above here*/
357 __DEVLINK_PARAM_GENERIC_ID_MAX,
358 DEVLINK_PARAM_GENERIC_ID_MAX = __DEVLINK_PARAM_GENERIC_ID_MAX - 1,
359};
360
298struct devlink_ops { 361struct devlink_ops {
299 int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack); 362 int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);
300 int (*port_type_set)(struct devlink_port *devlink_port, 363 int (*port_type_set)(struct devlink_port *devlink_port,
@@ -430,6 +493,12 @@ void devlink_resource_occ_get_register(struct devlink *devlink,
430 void *occ_get_priv); 493 void *occ_get_priv);
431void devlink_resource_occ_get_unregister(struct devlink *devlink, 494void devlink_resource_occ_get_unregister(struct devlink *devlink,
432 u64 resource_id); 495 u64 resource_id);
496int devlink_params_register(struct devlink *devlink,
497 const struct devlink_param *params,
498 size_t params_count);
499void devlink_params_unregister(struct devlink *devlink,
500 const struct devlink_param *params,
501 size_t params_count);
433 502
434#else 503#else
435 504
@@ -622,6 +691,22 @@ devlink_resource_occ_get_unregister(struct devlink *devlink,
622{ 691{
623} 692}
624 693
694static inline int
695devlink_params_register(struct devlink *devlink,
696 const struct devlink_param *params,
697 size_t params_count)
698{
699 return 0;
700}
701
702static inline void
703devlink_params_unregister(struct devlink *devlink,
704 const struct devlink_param *params,
705 size_t params_count)
706{
707
708}
709
625#endif 710#endif
626 711
627#endif /* _NET_DEVLINK_H_ */ 712#endif /* _NET_DEVLINK_H_ */
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 75cb5450c851..d814fa67c7b9 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -142,6 +142,16 @@ enum devlink_port_flavour {
142 */ 142 */
143}; 143};
144 144
145enum devlink_param_cmode {
146 DEVLINK_PARAM_CMODE_RUNTIME,
147 DEVLINK_PARAM_CMODE_DRIVERINIT,
148 DEVLINK_PARAM_CMODE_PERMANENT,
149
150 /* Add new configuration modes above */
151 __DEVLINK_PARAM_CMODE_MAX,
152 DEVLINK_PARAM_CMODE_MAX = __DEVLINK_PARAM_CMODE_MAX - 1
153};
154
145enum devlink_attr { 155enum devlink_attr {
146 /* don't change the order or add anything between, this is ABI! */ 156 /* don't change the order or add anything between, this is ABI! */
147 DEVLINK_ATTR_UNSPEC, 157 DEVLINK_ATTR_UNSPEC,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 22099705cc41..41b1a5d1c992 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2604,6 +2604,82 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2604 return devlink->ops->reload(devlink, info->extack); 2604 return devlink->ops->reload(devlink, info->extack);
2605} 2605}
2606 2606
2607static const struct devlink_param devlink_param_generic[] = {};
2608
2609static int devlink_param_generic_verify(const struct devlink_param *param)
2610{
2611 /* verify it match generic parameter by id and name */
2612 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2613 return -EINVAL;
2614 if (strcmp(param->name, devlink_param_generic[param->id].name))
2615 return -ENOENT;
2616
2617 WARN_ON(param->type != devlink_param_generic[param->id].type);
2618
2619 return 0;
2620}
2621
2622static int devlink_param_driver_verify(const struct devlink_param *param)
2623{
2624 int i;
2625
2626 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2627 return -EINVAL;
2628 /* verify no such name in generic params */
2629 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2630 if (!strcmp(param->name, devlink_param_generic[i].name))
2631 return -EEXIST;
2632
2633 return 0;
2634}
2635
2636static struct devlink_param_item *
2637devlink_param_find_by_name(struct list_head *param_list,
2638 const char *param_name)
2639{
2640 struct devlink_param_item *param_item;
2641
2642 list_for_each_entry(param_item, param_list, list)
2643 if (!strcmp(param_item->param->name, param_name))
2644 return param_item;
2645 return NULL;
2646}
2647
2648static int devlink_param_register_one(struct devlink *devlink,
2649 const struct devlink_param *param)
2650{
2651 struct devlink_param_item *param_item;
2652
2653 if (devlink_param_find_by_name(&devlink->param_list,
2654 param->name))
2655 return -EEXIST;
2656
2657 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
2658 WARN_ON(param->get || param->set);
2659 else
2660 WARN_ON(!param->get || !param->set);
2661
2662 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
2663 if (!param_item)
2664 return -ENOMEM;
2665 param_item->param = param;
2666
2667 list_add_tail(&param_item->list, &devlink->param_list);
2668 return 0;
2669}
2670
2671static void devlink_param_unregister_one(struct devlink *devlink,
2672 const struct devlink_param *param)
2673{
2674 struct devlink_param_item *param_item;
2675
2676 param_item = devlink_param_find_by_name(&devlink->param_list,
2677 param->name);
2678 WARN_ON(!param_item);
2679 list_del(&param_item->list);
2680 kfree(param_item);
2681}
2682
2607static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 2683static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
2608 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 2684 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
2609 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 2685 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
@@ -2845,6 +2921,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
2845 INIT_LIST_HEAD(&devlink->sb_list); 2921 INIT_LIST_HEAD(&devlink->sb_list);
2846 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 2922 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
2847 INIT_LIST_HEAD(&devlink->resource_list); 2923 INIT_LIST_HEAD(&devlink->resource_list);
2924 INIT_LIST_HEAD(&devlink->param_list);
2848 mutex_init(&devlink->lock); 2925 mutex_init(&devlink->lock);
2849 return devlink; 2926 return devlink;
2850} 2927}
@@ -3434,6 +3511,77 @@ out:
3434} 3511}
3435EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 3512EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
3436 3513
3514/**
3515 * devlink_params_register - register configuration parameters
3516 *
3517 * @devlink: devlink
3518 * @params: configuration parameters array
3519 * @params_count: number of parameters provided
3520 *
3521 * Register the configuration parameters supported by the driver.
3522 */
3523int devlink_params_register(struct devlink *devlink,
3524 const struct devlink_param *params,
3525 size_t params_count)
3526{
3527 const struct devlink_param *param = params;
3528 int i;
3529 int err;
3530
3531 mutex_lock(&devlink->lock);
3532 for (i = 0; i < params_count; i++, param++) {
3533 if (!param || !param->name || !param->supported_cmodes) {
3534 err = -EINVAL;
3535 goto rollback;
3536 }
3537 if (param->generic) {
3538 err = devlink_param_generic_verify(param);
3539 if (err)
3540 goto rollback;
3541 } else {
3542 err = devlink_param_driver_verify(param);
3543 if (err)
3544 goto rollback;
3545 }
3546 err = devlink_param_register_one(devlink, param);
3547 if (err)
3548 goto rollback;
3549 }
3550
3551 mutex_unlock(&devlink->lock);
3552 return 0;
3553
3554rollback:
3555 if (!i)
3556 goto unlock;
3557 for (param--; i > 0; i--, param--)
3558 devlink_param_unregister_one(devlink, param);
3559unlock:
3560 mutex_unlock(&devlink->lock);
3561 return err;
3562}
3563EXPORT_SYMBOL_GPL(devlink_params_register);
3564
3565/**
3566 * devlink_params_unregister - unregister configuration parameters
3567 * @devlink: devlink
3568 * @params: configuration parameters to unregister
3569 * @params_count: number of parameters provided
3570 */
3571void devlink_params_unregister(struct devlink *devlink,
3572 const struct devlink_param *params,
3573 size_t params_count)
3574{
3575 const struct devlink_param *param = params;
3576 int i;
3577
3578 mutex_lock(&devlink->lock);
3579 for (i = 0; i < params_count; i++, param++)
3580 devlink_param_unregister_one(devlink, param);
3581 mutex_unlock(&devlink->lock);
3582}
3583EXPORT_SYMBOL_GPL(devlink_params_unregister);
3584
3437static int __init devlink_module_init(void) 3585static int __init devlink_module_init(void)
3438{ 3586{
3439 return genl_register_family(&devlink_nl_family); 3587 return genl_register_family(&devlink_nl_family);