~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/devlink/param.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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                              struct netlink_ext_ack *extack)
163 {
164         if (!param->set)
165                 return -EOPNOTSUPP;
166         return param->set(devlink, param->id, ctx, extack);
167 }
168 
169 static int
170 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
171 {
172         switch (param_type) {
173         case DEVLINK_PARAM_TYPE_U8:
174                 return NLA_U8;
175         case DEVLINK_PARAM_TYPE_U16:
176                 return NLA_U16;
177         case DEVLINK_PARAM_TYPE_U32:
178                 return NLA_U32;
179         case DEVLINK_PARAM_TYPE_STRING:
180                 return NLA_STRING;
181         case DEVLINK_PARAM_TYPE_BOOL:
182                 return NLA_FLAG;
183         default:
184                 return -EINVAL;
185         }
186 }
187 
188 static int
189 devlink_nl_param_value_fill_one(struct sk_buff *msg,
190                                 enum devlink_param_type type,
191                                 enum devlink_param_cmode cmode,
192                                 union devlink_param_value val)
193 {
194         struct nlattr *param_value_attr;
195 
196         param_value_attr = nla_nest_start_noflag(msg,
197                                                  DEVLINK_ATTR_PARAM_VALUE);
198         if (!param_value_attr)
199                 goto nla_put_failure;
200 
201         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
202                 goto value_nest_cancel;
203 
204         switch (type) {
205         case DEVLINK_PARAM_TYPE_U8:
206                 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
207                         goto value_nest_cancel;
208                 break;
209         case DEVLINK_PARAM_TYPE_U16:
210                 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
211                         goto value_nest_cancel;
212                 break;
213         case DEVLINK_PARAM_TYPE_U32:
214                 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
215                         goto value_nest_cancel;
216                 break;
217         case DEVLINK_PARAM_TYPE_STRING:
218                 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
219                                    val.vstr))
220                         goto value_nest_cancel;
221                 break;
222         case DEVLINK_PARAM_TYPE_BOOL:
223                 if (val.vbool &&
224                     nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
225                         goto value_nest_cancel;
226                 break;
227         }
228 
229         nla_nest_end(msg, param_value_attr);
230         return 0;
231 
232 value_nest_cancel:
233         nla_nest_cancel(msg, param_value_attr);
234 nla_put_failure:
235         return -EMSGSIZE;
236 }
237 
238 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
239                                  unsigned int port_index,
240                                  struct devlink_param_item *param_item,
241                                  enum devlink_command cmd,
242                                  u32 portid, u32 seq, int flags)
243 {
244         union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
245         bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
246         const struct devlink_param *param = param_item->param;
247         struct devlink_param_gset_ctx ctx;
248         struct nlattr *param_values_list;
249         struct nlattr *param_attr;
250         int nla_type;
251         void *hdr;
252         int err;
253         int i;
254 
255         /* Get value from driver part to driverinit configuration mode */
256         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
257                 if (!devlink_param_cmode_is_supported(param, i))
258                         continue;
259                 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
260                         if (param_item->driverinit_value_new_valid)
261                                 param_value[i] = param_item->driverinit_value_new;
262                         else if (param_item->driverinit_value_valid)
263                                 param_value[i] = param_item->driverinit_value;
264                         else
265                                 return -EOPNOTSUPP;
266                 } else {
267                         ctx.cmode = i;
268                         err = devlink_param_get(devlink, param, &ctx);
269                         if (err)
270                                 return err;
271                         param_value[i] = ctx.val;
272                 }
273                 param_value_set[i] = true;
274         }
275 
276         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
277         if (!hdr)
278                 return -EMSGSIZE;
279 
280         if (devlink_nl_put_handle(msg, devlink))
281                 goto genlmsg_cancel;
282 
283         if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
284             cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
285             cmd == DEVLINK_CMD_PORT_PARAM_DEL)
286                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
287                         goto genlmsg_cancel;
288 
289         param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
290         if (!param_attr)
291                 goto genlmsg_cancel;
292         if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
293                 goto param_nest_cancel;
294         if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
295                 goto param_nest_cancel;
296 
297         nla_type = devlink_param_type_to_nla_type(param->type);
298         if (nla_type < 0)
299                 goto param_nest_cancel;
300         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
301                 goto param_nest_cancel;
302 
303         param_values_list = nla_nest_start_noflag(msg,
304                                                   DEVLINK_ATTR_PARAM_VALUES_LIST);
305         if (!param_values_list)
306                 goto param_nest_cancel;
307 
308         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
309                 if (!param_value_set[i])
310                         continue;
311                 err = devlink_nl_param_value_fill_one(msg, param->type,
312                                                       i, param_value[i]);
313                 if (err)
314                         goto values_list_nest_cancel;
315         }
316 
317         nla_nest_end(msg, param_values_list);
318         nla_nest_end(msg, param_attr);
319         genlmsg_end(msg, hdr);
320         return 0;
321 
322 values_list_nest_cancel:
323         nla_nest_end(msg, param_values_list);
324 param_nest_cancel:
325         nla_nest_cancel(msg, param_attr);
326 genlmsg_cancel:
327         genlmsg_cancel(msg, hdr);
328         return -EMSGSIZE;
329 }
330 
331 static void devlink_param_notify(struct devlink *devlink,
332                                  unsigned int port_index,
333                                  struct devlink_param_item *param_item,
334                                  enum devlink_command cmd)
335 {
336         struct sk_buff *msg;
337         int err;
338 
339         WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
340                 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
341                 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
342 
343         /* devlink_notify_register() / devlink_notify_unregister()
344          * will replay the notifications if the params are added/removed
345          * outside of the lifetime of the instance.
346          */
347         if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
348                 return;
349 
350         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
351         if (!msg)
352                 return;
353         err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
354                                     0, 0, 0);
355         if (err) {
356                 nlmsg_free(msg);
357                 return;
358         }
359 
360         devlink_nl_notify_send(devlink, msg);
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, info->extack);
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_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_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_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_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);
866 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php