GNU Linux-libre 6.8.7-gnu
[releases.git] / net / devlink / param.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5  */
6
7 #include "devl_internal.h"
8
9 static const struct devlink_param devlink_param_generic[] = {
10         {
11                 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
12                 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
13                 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
14         },
15         {
16                 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
17                 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
18                 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
19         },
20         {
21                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
22                 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
23                 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
24         },
25         {
26                 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
27                 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
28                 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
29         },
30         {
31                 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
32                 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
33                 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
34         },
35         {
36                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
37                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
38                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
39         },
40         {
41                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
42                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
43                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
44         },
45         {
46                 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
47                 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
48                 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
49         },
50         {
51                 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
52                 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
53                 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
54         },
55         {
56                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
57                 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
58                 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
59         },
60         {
61                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET,
62                 .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME,
63                 .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE,
64         },
65         {
66                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
67                 .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME,
68                 .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE,
69         },
70         {
71                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
72                 .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME,
73                 .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE,
74         },
75         {
76                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
77                 .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME,
78                 .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE,
79         },
80         {
81                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
82                 .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME,
83                 .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE,
84         },
85         {
86                 .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
87                 .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME,
88                 .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE,
89         },
90         {
91                 .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
92                 .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME,
93                 .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE,
94         },
95 };
96
97 static int devlink_param_generic_verify(const struct devlink_param *param)
98 {
99         /* verify it match generic parameter by id and name */
100         if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
101                 return -EINVAL;
102         if (strcmp(param->name, devlink_param_generic[param->id].name))
103                 return -ENOENT;
104
105         WARN_ON(param->type != devlink_param_generic[param->id].type);
106
107         return 0;
108 }
109
110 static int devlink_param_driver_verify(const struct devlink_param *param)
111 {
112         int i;
113
114         if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
115                 return -EINVAL;
116         /* verify no such name in generic params */
117         for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
118                 if (!strcmp(param->name, devlink_param_generic[i].name))
119                         return -EEXIST;
120
121         return 0;
122 }
123
124 static struct devlink_param_item *
125 devlink_param_find_by_name(struct xarray *params, const char *param_name)
126 {
127         struct devlink_param_item *param_item;
128         unsigned long param_id;
129
130         xa_for_each(params, param_id, param_item) {
131                 if (!strcmp(param_item->param->name, param_name))
132                         return param_item;
133         }
134         return NULL;
135 }
136
137 static struct devlink_param_item *
138 devlink_param_find_by_id(struct xarray *params, u32 param_id)
139 {
140         return xa_load(params, param_id);
141 }
142
143 static bool
144 devlink_param_cmode_is_supported(const struct devlink_param *param,
145                                  enum devlink_param_cmode cmode)
146 {
147         return test_bit(cmode, &param->supported_cmodes);
148 }
149
150 static int devlink_param_get(struct devlink *devlink,
151                              const struct devlink_param *param,
152                              struct devlink_param_gset_ctx *ctx)
153 {
154         if (!param->get)
155                 return -EOPNOTSUPP;
156         return param->get(devlink, param->id, ctx);
157 }
158
159 static int devlink_param_set(struct devlink *devlink,
160                              const struct devlink_param *param,
161                              struct devlink_param_gset_ctx *ctx)
162 {
163         if (!param->set)
164                 return -EOPNOTSUPP;
165         return param->set(devlink, param->id, ctx);
166 }
167
168 static int
169 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
170 {
171         switch (param_type) {
172         case DEVLINK_PARAM_TYPE_U8:
173                 return NLA_U8;
174         case DEVLINK_PARAM_TYPE_U16:
175                 return NLA_U16;
176         case DEVLINK_PARAM_TYPE_U32:
177                 return NLA_U32;
178         case DEVLINK_PARAM_TYPE_STRING:
179                 return NLA_STRING;
180         case DEVLINK_PARAM_TYPE_BOOL:
181                 return NLA_FLAG;
182         default:
183                 return -EINVAL;
184         }
185 }
186
187 static int
188 devlink_nl_param_value_fill_one(struct sk_buff *msg,
189                                 enum devlink_param_type type,
190                                 enum devlink_param_cmode cmode,
191                                 union devlink_param_value val)
192 {
193         struct nlattr *param_value_attr;
194
195         param_value_attr = nla_nest_start_noflag(msg,
196                                                  DEVLINK_ATTR_PARAM_VALUE);
197         if (!param_value_attr)
198                 goto nla_put_failure;
199
200         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
201                 goto value_nest_cancel;
202
203         switch (type) {
204         case DEVLINK_PARAM_TYPE_U8:
205                 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
206                         goto value_nest_cancel;
207                 break;
208         case DEVLINK_PARAM_TYPE_U16:
209                 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
210                         goto value_nest_cancel;
211                 break;
212         case DEVLINK_PARAM_TYPE_U32:
213                 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
214                         goto value_nest_cancel;
215                 break;
216         case DEVLINK_PARAM_TYPE_STRING:
217                 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
218                                    val.vstr))
219                         goto value_nest_cancel;
220                 break;
221         case DEVLINK_PARAM_TYPE_BOOL:
222                 if (val.vbool &&
223                     nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
224                         goto value_nest_cancel;
225                 break;
226         }
227
228         nla_nest_end(msg, param_value_attr);
229         return 0;
230
231 value_nest_cancel:
232         nla_nest_cancel(msg, param_value_attr);
233 nla_put_failure:
234         return -EMSGSIZE;
235 }
236
237 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
238                                  unsigned int port_index,
239                                  struct devlink_param_item *param_item,
240                                  enum devlink_command cmd,
241                                  u32 portid, u32 seq, int flags)
242 {
243         union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
244         bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
245         const struct devlink_param *param = param_item->param;
246         struct devlink_param_gset_ctx ctx;
247         struct nlattr *param_values_list;
248         struct nlattr *param_attr;
249         int nla_type;
250         void *hdr;
251         int err;
252         int i;
253
254         /* Get value from driver part to driverinit configuration mode */
255         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
256                 if (!devlink_param_cmode_is_supported(param, i))
257                         continue;
258                 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
259                         if (param_item->driverinit_value_new_valid)
260                                 param_value[i] = param_item->driverinit_value_new;
261                         else if (param_item->driverinit_value_valid)
262                                 param_value[i] = param_item->driverinit_value;
263                         else
264                                 return -EOPNOTSUPP;
265                 } else {
266                         ctx.cmode = i;
267                         err = devlink_param_get(devlink, param, &ctx);
268                         if (err)
269                                 return err;
270                         param_value[i] = ctx.val;
271                 }
272                 param_value_set[i] = true;
273         }
274
275         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
276         if (!hdr)
277                 return -EMSGSIZE;
278
279         if (devlink_nl_put_handle(msg, devlink))
280                 goto genlmsg_cancel;
281
282         if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
283             cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
284             cmd == DEVLINK_CMD_PORT_PARAM_DEL)
285                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
286                         goto genlmsg_cancel;
287
288         param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
289         if (!param_attr)
290                 goto genlmsg_cancel;
291         if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
292                 goto param_nest_cancel;
293         if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
294                 goto param_nest_cancel;
295
296         nla_type = devlink_param_type_to_nla_type(param->type);
297         if (nla_type < 0)
298                 goto param_nest_cancel;
299         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
300                 goto param_nest_cancel;
301
302         param_values_list = nla_nest_start_noflag(msg,
303                                                   DEVLINK_ATTR_PARAM_VALUES_LIST);
304         if (!param_values_list)
305                 goto param_nest_cancel;
306
307         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
308                 if (!param_value_set[i])
309                         continue;
310                 err = devlink_nl_param_value_fill_one(msg, param->type,
311                                                       i, param_value[i]);
312                 if (err)
313                         goto values_list_nest_cancel;
314         }
315
316         nla_nest_end(msg, param_values_list);
317         nla_nest_end(msg, param_attr);
318         genlmsg_end(msg, hdr);
319         return 0;
320
321 values_list_nest_cancel:
322         nla_nest_end(msg, param_values_list);
323 param_nest_cancel:
324         nla_nest_cancel(msg, param_attr);
325 genlmsg_cancel:
326         genlmsg_cancel(msg, hdr);
327         return -EMSGSIZE;
328 }
329
330 static void devlink_param_notify(struct devlink *devlink,
331                                  unsigned int port_index,
332                                  struct devlink_param_item *param_item,
333                                  enum devlink_command cmd)
334 {
335         struct sk_buff *msg;
336         int err;
337
338         WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
339                 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
340                 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
341
342         /* devlink_notify_register() / devlink_notify_unregister()
343          * will replay the notifications if the params are added/removed
344          * outside of the lifetime of the instance.
345          */
346         if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
347                 return;
348
349         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
350         if (!msg)
351                 return;
352         err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
353                                     0, 0, 0);
354         if (err) {
355                 nlmsg_free(msg);
356                 return;
357         }
358
359         devlink_nl_notify_send(devlink, msg);
360 }
361
362 static void devlink_params_notify(struct devlink *devlink,
363                                   enum devlink_command cmd)
364 {
365         struct devlink_param_item *param_item;
366         unsigned long param_id;
367
368         xa_for_each(&devlink->params, param_id, param_item)
369                 devlink_param_notify(devlink, 0, param_item, cmd);
370 }
371
372 void devlink_params_notify_register(struct devlink *devlink)
373 {
374         devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
375 }
376
377 void devlink_params_notify_unregister(struct devlink *devlink)
378 {
379         devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
380 }
381
382 static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
383                                          struct devlink *devlink,
384                                          struct netlink_callback *cb,
385                                          int flags)
386 {
387         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
388         struct devlink_param_item *param_item;
389         unsigned long param_id;
390         int err = 0;
391
392         xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
393                 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
394                                             DEVLINK_CMD_PARAM_GET,
395                                             NETLINK_CB(cb->skb).portid,
396                                             cb->nlh->nlmsg_seq, flags);
397                 if (err == -EOPNOTSUPP) {
398                         err = 0;
399                 } else if (err) {
400                         state->idx = param_id;
401                         break;
402                 }
403         }
404
405         return err;
406 }
407
408 int devlink_nl_param_get_dumpit(struct sk_buff *skb,
409                                 struct netlink_callback *cb)
410 {
411         return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
412 }
413
414 static int
415 devlink_param_type_get_from_info(struct genl_info *info,
416                                  enum devlink_param_type *param_type)
417 {
418         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
419                 return -EINVAL;
420
421         switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
422         case NLA_U8:
423                 *param_type = DEVLINK_PARAM_TYPE_U8;
424                 break;
425         case NLA_U16:
426                 *param_type = DEVLINK_PARAM_TYPE_U16;
427                 break;
428         case NLA_U32:
429                 *param_type = DEVLINK_PARAM_TYPE_U32;
430                 break;
431         case NLA_STRING:
432                 *param_type = DEVLINK_PARAM_TYPE_STRING;
433                 break;
434         case NLA_FLAG:
435                 *param_type = DEVLINK_PARAM_TYPE_BOOL;
436                 break;
437         default:
438                 return -EINVAL;
439         }
440
441         return 0;
442 }
443
444 static int
445 devlink_param_value_get_from_info(const struct devlink_param *param,
446                                   struct genl_info *info,
447                                   union devlink_param_value *value)
448 {
449         struct nlattr *param_data;
450         int len;
451
452         param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
453
454         if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
455                 return -EINVAL;
456
457         switch (param->type) {
458         case DEVLINK_PARAM_TYPE_U8:
459                 if (nla_len(param_data) != sizeof(u8))
460                         return -EINVAL;
461                 value->vu8 = nla_get_u8(param_data);
462                 break;
463         case DEVLINK_PARAM_TYPE_U16:
464                 if (nla_len(param_data) != sizeof(u16))
465                         return -EINVAL;
466                 value->vu16 = nla_get_u16(param_data);
467                 break;
468         case DEVLINK_PARAM_TYPE_U32:
469                 if (nla_len(param_data) != sizeof(u32))
470                         return -EINVAL;
471                 value->vu32 = nla_get_u32(param_data);
472                 break;
473         case DEVLINK_PARAM_TYPE_STRING:
474                 len = strnlen(nla_data(param_data), nla_len(param_data));
475                 if (len == nla_len(param_data) ||
476                     len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
477                         return -EINVAL;
478                 strcpy(value->vstr, nla_data(param_data));
479                 break;
480         case DEVLINK_PARAM_TYPE_BOOL:
481                 if (param_data && nla_len(param_data))
482                         return -EINVAL;
483                 value->vbool = nla_get_flag(param_data);
484                 break;
485         }
486         return 0;
487 }
488
489 static struct devlink_param_item *
490 devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
491 {
492         char *param_name;
493
494         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
495                 return NULL;
496
497         param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
498         return devlink_param_find_by_name(params, param_name);
499 }
500
501 int devlink_nl_param_get_doit(struct sk_buff *skb,
502                               struct genl_info *info)
503 {
504         struct devlink *devlink = info->user_ptr[0];
505         struct devlink_param_item *param_item;
506         struct sk_buff *msg;
507         int err;
508
509         param_item = devlink_param_get_from_info(&devlink->params, info);
510         if (!param_item)
511                 return -EINVAL;
512
513         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
514         if (!msg)
515                 return -ENOMEM;
516
517         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
518                                     DEVLINK_CMD_PARAM_GET,
519                                     info->snd_portid, info->snd_seq, 0);
520         if (err) {
521                 nlmsg_free(msg);
522                 return err;
523         }
524
525         return genlmsg_reply(msg, info);
526 }
527
528 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
529                                            unsigned int port_index,
530                                            struct xarray *params,
531                                            struct genl_info *info,
532                                            enum devlink_command cmd)
533 {
534         enum devlink_param_type param_type;
535         struct devlink_param_gset_ctx ctx;
536         enum devlink_param_cmode cmode;
537         struct devlink_param_item *param_item;
538         const struct devlink_param *param;
539         union devlink_param_value value;
540         int err = 0;
541
542         param_item = devlink_param_get_from_info(params, info);
543         if (!param_item)
544                 return -EINVAL;
545         param = param_item->param;
546         err = devlink_param_type_get_from_info(info, &param_type);
547         if (err)
548                 return err;
549         if (param_type != param->type)
550                 return -EINVAL;
551         err = devlink_param_value_get_from_info(param, info, &value);
552         if (err)
553                 return err;
554         if (param->validate) {
555                 err = param->validate(devlink, param->id, value, info->extack);
556                 if (err)
557                         return err;
558         }
559
560         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
561                 return -EINVAL;
562         cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
563         if (!devlink_param_cmode_is_supported(param, cmode))
564                 return -EOPNOTSUPP;
565
566         if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
567                 param_item->driverinit_value_new = value;
568                 param_item->driverinit_value_new_valid = true;
569         } else {
570                 if (!param->set)
571                         return -EOPNOTSUPP;
572                 ctx.val = value;
573                 ctx.cmode = cmode;
574                 err = devlink_param_set(devlink, param, &ctx);
575                 if (err)
576                         return err;
577         }
578
579         devlink_param_notify(devlink, port_index, param_item, cmd);
580         return 0;
581 }
582
583 int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info)
584 {
585         struct devlink *devlink = info->user_ptr[0];
586
587         return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
588                                                info, DEVLINK_CMD_PARAM_NEW);
589 }
590
591 int devlink_nl_port_param_get_dumpit(struct sk_buff *msg,
592                                      struct netlink_callback *cb)
593 {
594         NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
595         return msg->len;
596 }
597
598 int devlink_nl_port_param_get_doit(struct sk_buff *skb,
599                                    struct genl_info *info)
600 {
601         NL_SET_ERR_MSG(info->extack, "Port params are not supported");
602         return -EINVAL;
603 }
604
605 int devlink_nl_port_param_set_doit(struct sk_buff *skb,
606                                    struct genl_info *info)
607 {
608         NL_SET_ERR_MSG(info->extack, "Port params are not supported");
609         return -EINVAL;
610 }
611
612 static int devlink_param_verify(const struct devlink_param *param)
613 {
614         if (!param || !param->name || !param->supported_cmodes)
615                 return -EINVAL;
616         if (param->generic)
617                 return devlink_param_generic_verify(param);
618         else
619                 return devlink_param_driver_verify(param);
620 }
621
622 static int devlink_param_register(struct devlink *devlink,
623                                   const struct devlink_param *param)
624 {
625         struct devlink_param_item *param_item;
626         int err;
627
628         WARN_ON(devlink_param_verify(param));
629         WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
630
631         if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
632                 WARN_ON(param->get || param->set);
633         else
634                 WARN_ON(!param->get || !param->set);
635
636         param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
637         if (!param_item)
638                 return -ENOMEM;
639
640         param_item->param = param;
641
642         err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
643         if (err)
644                 goto err_xa_insert;
645
646         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
647         return 0;
648
649 err_xa_insert:
650         kfree(param_item);
651         return err;
652 }
653
654 static void devlink_param_unregister(struct devlink *devlink,
655                                      const struct devlink_param *param)
656 {
657         struct devlink_param_item *param_item;
658
659         param_item = devlink_param_find_by_id(&devlink->params, param->id);
660         if (WARN_ON(!param_item))
661                 return;
662         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
663         xa_erase(&devlink->params, param->id);
664         kfree(param_item);
665 }
666
667 /**
668  *      devl_params_register - register configuration parameters
669  *
670  *      @devlink: devlink
671  *      @params: configuration parameters array
672  *      @params_count: number of parameters provided
673  *
674  *      Register the configuration parameters supported by the driver.
675  */
676 int devl_params_register(struct devlink *devlink,
677                          const struct devlink_param *params,
678                          size_t params_count)
679 {
680         const struct devlink_param *param = params;
681         int i, err;
682
683         lockdep_assert_held(&devlink->lock);
684
685         for (i = 0; i < params_count; i++, param++) {
686                 err = devlink_param_register(devlink, param);
687                 if (err)
688                         goto rollback;
689         }
690         return 0;
691
692 rollback:
693         if (!i)
694                 return err;
695
696         for (param--; i > 0; i--, param--)
697                 devlink_param_unregister(devlink, param);
698         return err;
699 }
700 EXPORT_SYMBOL_GPL(devl_params_register);
701
702 int devlink_params_register(struct devlink *devlink,
703                             const struct devlink_param *params,
704                             size_t params_count)
705 {
706         int err;
707
708         devl_lock(devlink);
709         err = devl_params_register(devlink, params, params_count);
710         devl_unlock(devlink);
711         return err;
712 }
713 EXPORT_SYMBOL_GPL(devlink_params_register);
714
715 /**
716  *      devl_params_unregister - unregister configuration parameters
717  *      @devlink: devlink
718  *      @params: configuration parameters to unregister
719  *      @params_count: number of parameters provided
720  */
721 void devl_params_unregister(struct devlink *devlink,
722                             const struct devlink_param *params,
723                             size_t params_count)
724 {
725         const struct devlink_param *param = params;
726         int i;
727
728         lockdep_assert_held(&devlink->lock);
729
730         for (i = 0; i < params_count; i++, param++)
731                 devlink_param_unregister(devlink, param);
732 }
733 EXPORT_SYMBOL_GPL(devl_params_unregister);
734
735 void devlink_params_unregister(struct devlink *devlink,
736                                const struct devlink_param *params,
737                                size_t params_count)
738 {
739         devl_lock(devlink);
740         devl_params_unregister(devlink, params, params_count);
741         devl_unlock(devlink);
742 }
743 EXPORT_SYMBOL_GPL(devlink_params_unregister);
744
745 /**
746  *      devl_param_driverinit_value_get - get configuration parameter
747  *                                        value for driver initializing
748  *
749  *      @devlink: devlink
750  *      @param_id: parameter ID
751  *      @val: pointer to store the value of parameter in driverinit
752  *            configuration mode
753  *
754  *      This function should be used by the driver to get driverinit
755  *      configuration for initialization after reload command.
756  *
757  *      Note that lockless call of this function relies on the
758  *      driver to maintain following basic sane behavior:
759  *      1) Driver ensures a call to this function cannot race with
760  *         registering/unregistering the parameter with the same parameter ID.
761  *      2) Driver ensures a call to this function cannot race with
762  *         devl_param_driverinit_value_set() call with the same parameter ID.
763  *      3) Driver ensures a call to this function cannot race with
764  *         reload operation.
765  *      If the driver is not able to comply, it has to take the devlink->lock
766  *      while calling this.
767  */
768 int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
769                                     union devlink_param_value *val)
770 {
771         struct devlink_param_item *param_item;
772
773         if (WARN_ON(!devlink_reload_supported(devlink->ops)))
774                 return -EOPNOTSUPP;
775
776         param_item = devlink_param_find_by_id(&devlink->params, param_id);
777         if (!param_item)
778                 return -EINVAL;
779
780         if (!param_item->driverinit_value_valid)
781                 return -EOPNOTSUPP;
782
783         if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
784                                                       DEVLINK_PARAM_CMODE_DRIVERINIT)))
785                 return -EOPNOTSUPP;
786
787         *val = param_item->driverinit_value;
788
789         return 0;
790 }
791 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
792
793 /**
794  *      devl_param_driverinit_value_set - set value of configuration
795  *                                        parameter for driverinit
796  *                                        configuration mode
797  *
798  *      @devlink: devlink
799  *      @param_id: parameter ID
800  *      @init_val: value of parameter to set for driverinit configuration mode
801  *
802  *      This function should be used by the driver to set driverinit
803  *      configuration mode default value.
804  */
805 void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
806                                      union devlink_param_value init_val)
807 {
808         struct devlink_param_item *param_item;
809
810         devl_assert_locked(devlink);
811
812         param_item = devlink_param_find_by_id(&devlink->params, param_id);
813         if (WARN_ON(!param_item))
814                 return;
815
816         if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
817                                                       DEVLINK_PARAM_CMODE_DRIVERINIT)))
818                 return;
819
820         param_item->driverinit_value = init_val;
821         param_item->driverinit_value_valid = true;
822
823         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
824 }
825 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
826
827 void devlink_params_driverinit_load_new(struct devlink *devlink)
828 {
829         struct devlink_param_item *param_item;
830         unsigned long param_id;
831
832         xa_for_each(&devlink->params, param_id, param_item) {
833                 if (!devlink_param_cmode_is_supported(param_item->param,
834                                                       DEVLINK_PARAM_CMODE_DRIVERINIT) ||
835                     !param_item->driverinit_value_new_valid)
836                         continue;
837                 param_item->driverinit_value = param_item->driverinit_value_new;
838                 param_item->driverinit_value_valid = true;
839                 param_item->driverinit_value_new_valid = false;
840         }
841 }
842
843 /**
844  *      devl_param_value_changed - notify devlink on a parameter's value
845  *                                 change. Should be called by the driver
846  *                                 right after the change.
847  *
848  *      @devlink: devlink
849  *      @param_id: parameter ID
850  *
851  *      This function should be used by the driver to notify devlink on value
852  *      change, excluding driverinit configuration mode.
853  *      For driverinit configuration mode driver should use the function
854  */
855 void devl_param_value_changed(struct devlink *devlink, u32 param_id)
856 {
857         struct devlink_param_item *param_item;
858
859         param_item = devlink_param_find_by_id(&devlink->params, param_id);
860         WARN_ON(!param_item);
861
862         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
863 }
864 EXPORT_SYMBOL_GPL(devl_param_value_changed);