USB: serial: option: add Fibocom FM101-GL variant
[platform/kernel/linux-rpi.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))
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         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
360                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
361 }
362
363 static void devlink_params_notify(struct devlink *devlink,
364                                   enum devlink_command cmd)
365 {
366         struct devlink_param_item *param_item;
367         unsigned long param_id;
368
369         xa_for_each(&devlink->params, param_id, param_item)
370                 devlink_param_notify(devlink, 0, param_item, cmd);
371 }
372
373 void devlink_params_notify_register(struct devlink *devlink)
374 {
375         devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
376 }
377
378 void devlink_params_notify_unregister(struct devlink *devlink)
379 {
380         devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
381 }
382
383 static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
384                                          struct devlink *devlink,
385                                          struct netlink_callback *cb,
386                                          int flags)
387 {
388         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
389         struct devlink_param_item *param_item;
390         unsigned long param_id;
391         int err = 0;
392
393         xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
394                 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
395                                             DEVLINK_CMD_PARAM_GET,
396                                             NETLINK_CB(cb->skb).portid,
397                                             cb->nlh->nlmsg_seq, flags);
398                 if (err == -EOPNOTSUPP) {
399                         err = 0;
400                 } else if (err) {
401                         state->idx = param_id;
402                         break;
403                 }
404         }
405
406         return err;
407 }
408
409 int devlink_nl_param_get_dumpit(struct sk_buff *skb,
410                                 struct netlink_callback *cb)
411 {
412         return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
413 }
414
415 static int
416 devlink_param_type_get_from_info(struct genl_info *info,
417                                  enum devlink_param_type *param_type)
418 {
419         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
420                 return -EINVAL;
421
422         switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
423         case NLA_U8:
424                 *param_type = DEVLINK_PARAM_TYPE_U8;
425                 break;
426         case NLA_U16:
427                 *param_type = DEVLINK_PARAM_TYPE_U16;
428                 break;
429         case NLA_U32:
430                 *param_type = DEVLINK_PARAM_TYPE_U32;
431                 break;
432         case NLA_STRING:
433                 *param_type = DEVLINK_PARAM_TYPE_STRING;
434                 break;
435         case NLA_FLAG:
436                 *param_type = DEVLINK_PARAM_TYPE_BOOL;
437                 break;
438         default:
439                 return -EINVAL;
440         }
441
442         return 0;
443 }
444
445 static int
446 devlink_param_value_get_from_info(const struct devlink_param *param,
447                                   struct genl_info *info,
448                                   union devlink_param_value *value)
449 {
450         struct nlattr *param_data;
451         int len;
452
453         param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
454
455         if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
456                 return -EINVAL;
457
458         switch (param->type) {
459         case DEVLINK_PARAM_TYPE_U8:
460                 if (nla_len(param_data) != sizeof(u8))
461                         return -EINVAL;
462                 value->vu8 = nla_get_u8(param_data);
463                 break;
464         case DEVLINK_PARAM_TYPE_U16:
465                 if (nla_len(param_data) != sizeof(u16))
466                         return -EINVAL;
467                 value->vu16 = nla_get_u16(param_data);
468                 break;
469         case DEVLINK_PARAM_TYPE_U32:
470                 if (nla_len(param_data) != sizeof(u32))
471                         return -EINVAL;
472                 value->vu32 = nla_get_u32(param_data);
473                 break;
474         case DEVLINK_PARAM_TYPE_STRING:
475                 len = strnlen(nla_data(param_data), nla_len(param_data));
476                 if (len == nla_len(param_data) ||
477                     len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
478                         return -EINVAL;
479                 strcpy(value->vstr, nla_data(param_data));
480                 break;
481         case DEVLINK_PARAM_TYPE_BOOL:
482                 if (param_data && nla_len(param_data))
483                         return -EINVAL;
484                 value->vbool = nla_get_flag(param_data);
485                 break;
486         }
487         return 0;
488 }
489
490 static struct devlink_param_item *
491 devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
492 {
493         char *param_name;
494
495         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
496                 return NULL;
497
498         param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
499         return devlink_param_find_by_name(params, param_name);
500 }
501
502 int devlink_nl_param_get_doit(struct sk_buff *skb,
503                               struct genl_info *info)
504 {
505         struct devlink *devlink = info->user_ptr[0];
506         struct devlink_param_item *param_item;
507         struct sk_buff *msg;
508         int err;
509
510         param_item = devlink_param_get_from_info(&devlink->params, info);
511         if (!param_item)
512                 return -EINVAL;
513
514         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
515         if (!msg)
516                 return -ENOMEM;
517
518         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
519                                     DEVLINK_CMD_PARAM_GET,
520                                     info->snd_portid, info->snd_seq, 0);
521         if (err) {
522                 nlmsg_free(msg);
523                 return err;
524         }
525
526         return genlmsg_reply(msg, info);
527 }
528
529 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
530                                            unsigned int port_index,
531                                            struct xarray *params,
532                                            struct genl_info *info,
533                                            enum devlink_command cmd)
534 {
535         enum devlink_param_type param_type;
536         struct devlink_param_gset_ctx ctx;
537         enum devlink_param_cmode cmode;
538         struct devlink_param_item *param_item;
539         const struct devlink_param *param;
540         union devlink_param_value value;
541         int err = 0;
542
543         param_item = devlink_param_get_from_info(params, info);
544         if (!param_item)
545                 return -EINVAL;
546         param = param_item->param;
547         err = devlink_param_type_get_from_info(info, &param_type);
548         if (err)
549                 return err;
550         if (param_type != param->type)
551                 return -EINVAL;
552         err = devlink_param_value_get_from_info(param, info, &value);
553         if (err)
554                 return err;
555         if (param->validate) {
556                 err = param->validate(devlink, param->id, value, info->extack);
557                 if (err)
558                         return err;
559         }
560
561         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
562                 return -EINVAL;
563         cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
564         if (!devlink_param_cmode_is_supported(param, cmode))
565                 return -EOPNOTSUPP;
566
567         if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
568                 param_item->driverinit_value_new = value;
569                 param_item->driverinit_value_new_valid = true;
570         } else {
571                 if (!param->set)
572                         return -EOPNOTSUPP;
573                 ctx.val = value;
574                 ctx.cmode = cmode;
575                 err = devlink_param_set(devlink, param, &ctx);
576                 if (err)
577                         return err;
578         }
579
580         devlink_param_notify(devlink, port_index, param_item, cmd);
581         return 0;
582 }
583
584 int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, struct genl_info *info)
585 {
586         struct devlink *devlink = info->user_ptr[0];
587
588         return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
589                                                info, DEVLINK_CMD_PARAM_NEW);
590 }
591
592 int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
593                                          struct netlink_callback *cb)
594 {
595         NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
596         return msg->len;
597 }
598
599 int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
600                                        struct genl_info *info)
601 {
602         NL_SET_ERR_MSG(info->extack, "Port params are not supported");
603         return -EINVAL;
604 }
605
606 int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
607                                        struct genl_info *info)
608 {
609         NL_SET_ERR_MSG(info->extack, "Port params are not supported");
610         return -EINVAL;
611 }
612
613 static int devlink_param_verify(const struct devlink_param *param)
614 {
615         if (!param || !param->name || !param->supported_cmodes)
616                 return -EINVAL;
617         if (param->generic)
618                 return devlink_param_generic_verify(param);
619         else
620                 return devlink_param_driver_verify(param);
621 }
622
623 static int devlink_param_register(struct devlink *devlink,
624                                   const struct devlink_param *param)
625 {
626         struct devlink_param_item *param_item;
627         int err;
628
629         WARN_ON(devlink_param_verify(param));
630         WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
631
632         if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
633                 WARN_ON(param->get || param->set);
634         else
635                 WARN_ON(!param->get || !param->set);
636
637         param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
638         if (!param_item)
639                 return -ENOMEM;
640
641         param_item->param = param;
642
643         err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
644         if (err)
645                 goto err_xa_insert;
646
647         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
648         return 0;
649
650 err_xa_insert:
651         kfree(param_item);
652         return err;
653 }
654
655 static void devlink_param_unregister(struct devlink *devlink,
656                                      const struct devlink_param *param)
657 {
658         struct devlink_param_item *param_item;
659
660         param_item = devlink_param_find_by_id(&devlink->params, param->id);
661         if (WARN_ON(!param_item))
662                 return;
663         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
664         xa_erase(&devlink->params, param->id);
665         kfree(param_item);
666 }
667
668 /**
669  *      devl_params_register - register configuration parameters
670  *
671  *      @devlink: devlink
672  *      @params: configuration parameters array
673  *      @params_count: number of parameters provided
674  *
675  *      Register the configuration parameters supported by the driver.
676  */
677 int devl_params_register(struct devlink *devlink,
678                          const struct devlink_param *params,
679                          size_t params_count)
680 {
681         const struct devlink_param *param = params;
682         int i, err;
683
684         lockdep_assert_held(&devlink->lock);
685
686         for (i = 0; i < params_count; i++, param++) {
687                 err = devlink_param_register(devlink, param);
688                 if (err)
689                         goto rollback;
690         }
691         return 0;
692
693 rollback:
694         if (!i)
695                 return err;
696
697         for (param--; i > 0; i--, param--)
698                 devlink_param_unregister(devlink, param);
699         return err;
700 }
701 EXPORT_SYMBOL_GPL(devl_params_register);
702
703 int devlink_params_register(struct devlink *devlink,
704                             const struct devlink_param *params,
705                             size_t params_count)
706 {
707         int err;
708
709         devl_lock(devlink);
710         err = devl_params_register(devlink, params, params_count);
711         devl_unlock(devlink);
712         return err;
713 }
714 EXPORT_SYMBOL_GPL(devlink_params_register);
715
716 /**
717  *      devl_params_unregister - unregister configuration parameters
718  *      @devlink: devlink
719  *      @params: configuration parameters to unregister
720  *      @params_count: number of parameters provided
721  */
722 void devl_params_unregister(struct devlink *devlink,
723                             const struct devlink_param *params,
724                             size_t params_count)
725 {
726         const struct devlink_param *param = params;
727         int i;
728
729         lockdep_assert_held(&devlink->lock);
730
731         for (i = 0; i < params_count; i++, param++)
732                 devlink_param_unregister(devlink, param);
733 }
734 EXPORT_SYMBOL_GPL(devl_params_unregister);
735
736 void devlink_params_unregister(struct devlink *devlink,
737                                const struct devlink_param *params,
738                                size_t params_count)
739 {
740         devl_lock(devlink);
741         devl_params_unregister(devlink, params, params_count);
742         devl_unlock(devlink);
743 }
744 EXPORT_SYMBOL_GPL(devlink_params_unregister);
745
746 /**
747  *      devl_param_driverinit_value_get - get configuration parameter
748  *                                        value for driver initializing
749  *
750  *      @devlink: devlink
751  *      @param_id: parameter ID
752  *      @val: pointer to store the value of parameter in driverinit
753  *            configuration mode
754  *
755  *      This function should be used by the driver to get driverinit
756  *      configuration for initialization after reload command.
757  *
758  *      Note that lockless call of this function relies on the
759  *      driver to maintain following basic sane behavior:
760  *      1) Driver ensures a call to this function cannot race with
761  *         registering/unregistering the parameter with the same parameter ID.
762  *      2) Driver ensures a call to this function cannot race with
763  *         devl_param_driverinit_value_set() call with the same parameter ID.
764  *      3) Driver ensures a call to this function cannot race with
765  *         reload operation.
766  *      If the driver is not able to comply, it has to take the devlink->lock
767  *      while calling this.
768  */
769 int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
770                                     union devlink_param_value *val)
771 {
772         struct devlink_param_item *param_item;
773
774         if (WARN_ON(!devlink_reload_supported(devlink->ops)))
775                 return -EOPNOTSUPP;
776
777         param_item = devlink_param_find_by_id(&devlink->params, param_id);
778         if (!param_item)
779                 return -EINVAL;
780
781         if (!param_item->driverinit_value_valid)
782                 return -EOPNOTSUPP;
783
784         if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
785                                                       DEVLINK_PARAM_CMODE_DRIVERINIT)))
786                 return -EOPNOTSUPP;
787
788         *val = param_item->driverinit_value;
789
790         return 0;
791 }
792 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
793
794 /**
795  *      devl_param_driverinit_value_set - set value of configuration
796  *                                        parameter for driverinit
797  *                                        configuration mode
798  *
799  *      @devlink: devlink
800  *      @param_id: parameter ID
801  *      @init_val: value of parameter to set for driverinit configuration mode
802  *
803  *      This function should be used by the driver to set driverinit
804  *      configuration mode default value.
805  */
806 void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
807                                      union devlink_param_value init_val)
808 {
809         struct devlink_param_item *param_item;
810
811         devl_assert_locked(devlink);
812
813         param_item = devlink_param_find_by_id(&devlink->params, param_id);
814         if (WARN_ON(!param_item))
815                 return;
816
817         if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
818                                                       DEVLINK_PARAM_CMODE_DRIVERINIT)))
819                 return;
820
821         param_item->driverinit_value = init_val;
822         param_item->driverinit_value_valid = true;
823
824         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
825 }
826 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
827
828 void devlink_params_driverinit_load_new(struct devlink *devlink)
829 {
830         struct devlink_param_item *param_item;
831         unsigned long param_id;
832
833         xa_for_each(&devlink->params, param_id, param_item) {
834                 if (!devlink_param_cmode_is_supported(param_item->param,
835                                                       DEVLINK_PARAM_CMODE_DRIVERINIT) ||
836                     !param_item->driverinit_value_new_valid)
837                         continue;
838                 param_item->driverinit_value = param_item->driverinit_value_new;
839                 param_item->driverinit_value_valid = true;
840                 param_item->driverinit_value_new_valid = false;
841         }
842 }
843
844 /**
845  *      devl_param_value_changed - notify devlink on a parameter's value
846  *                                 change. Should be called by the driver
847  *                                 right after the change.
848  *
849  *      @devlink: devlink
850  *      @param_id: parameter ID
851  *
852  *      This function should be used by the driver to notify devlink on value
853  *      change, excluding driverinit configuration mode.
854  *      For driverinit configuration mode driver should use the function
855  */
856 void devl_param_value_changed(struct devlink *devlink, u32 param_id)
857 {
858         struct devlink_param_item *param_item;
859
860         param_item = devlink_param_find_by_id(&devlink->params, param_id);
861         WARN_ON(!param_item);
862
863         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
864 }
865 EXPORT_SYMBOL_GPL(devl_param_value_changed);