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 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
97 .name = DEVLINK_PARAM_GENERIC_ENABLE_PHC_NAME,
98 .type = DEVLINK_PARAM_GENERIC_ENABLE_PHC_TYPE,
99 },
100 {
101 .id = DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
102 .name = DEVLINK_PARAM_GENERIC_CLOCK_ID_NAME,
103 .type = DEVLINK_PARAM_GENERIC_CLOCK_ID_TYPE,
104 },
105 {
106 .id = DEVLINK_PARAM_GENERIC_ID_TOTAL_VFS,
107 .name = DEVLINK_PARAM_GENERIC_TOTAL_VFS_NAME,
108 .type = DEVLINK_PARAM_GENERIC_TOTAL_VFS_TYPE,
109 },
110 {
111 .id = DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS,
112 .name = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_NAME,
113 .type = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_TYPE,
114 },
115 {
116 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MAC_PER_VF,
117 .name = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_NAME,
118 .type = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_TYPE,
119 },
120 {
121 .id = DEVLINK_PARAM_GENERIC_ID_MAX_SFS,
122 .name = DEVLINK_PARAM_GENERIC_MAX_SFS_NAME,
123 .type = DEVLINK_PARAM_GENERIC_MAX_SFS_TYPE,
124 },
125 };
126
devlink_param_generic_verify(const struct devlink_param * param)127 static int devlink_param_generic_verify(const struct devlink_param *param)
128 {
129 /* verify it match generic parameter by id and name */
130 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
131 return -EINVAL;
132 if (strcmp(param->name, devlink_param_generic[param->id].name))
133 return -ENOENT;
134
135 WARN_ON(param->type != devlink_param_generic[param->id].type);
136
137 return 0;
138 }
139
devlink_param_driver_verify(const struct devlink_param * param)140 static int devlink_param_driver_verify(const struct devlink_param *param)
141 {
142 int i;
143
144 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
145 return -EINVAL;
146 /* verify no such name in generic params */
147 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
148 if (!strcmp(param->name, devlink_param_generic[i].name))
149 return -EEXIST;
150
151 return 0;
152 }
153
154 static struct devlink_param_item *
devlink_param_find_by_name(struct xarray * params,const char * param_name)155 devlink_param_find_by_name(struct xarray *params, const char *param_name)
156 {
157 struct devlink_param_item *param_item;
158 unsigned long param_id;
159
160 xa_for_each(params, param_id, param_item) {
161 if (!strcmp(param_item->param->name, param_name))
162 return param_item;
163 }
164 return NULL;
165 }
166
167 static struct devlink_param_item *
devlink_param_find_by_id(struct xarray * params,u32 param_id)168 devlink_param_find_by_id(struct xarray *params, u32 param_id)
169 {
170 return xa_load(params, param_id);
171 }
172
173 static bool
devlink_param_cmode_is_supported(const struct devlink_param * param,enum devlink_param_cmode cmode)174 devlink_param_cmode_is_supported(const struct devlink_param *param,
175 enum devlink_param_cmode cmode)
176 {
177 return test_bit(cmode, ¶m->supported_cmodes);
178 }
179
devlink_param_get(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)180 static int devlink_param_get(struct devlink *devlink,
181 const struct devlink_param *param,
182 struct devlink_param_gset_ctx *ctx,
183 struct netlink_ext_ack *extack)
184 {
185 if (!param->get)
186 return -EOPNOTSUPP;
187 return param->get(devlink, param->id, ctx, extack);
188 }
189
devlink_param_set(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)190 static int devlink_param_set(struct devlink *devlink,
191 const struct devlink_param *param,
192 struct devlink_param_gset_ctx *ctx,
193 struct netlink_ext_ack *extack)
194 {
195 if (!param->set)
196 return -EOPNOTSUPP;
197 return param->set(devlink, param->id, ctx, extack);
198 }
199
devlink_param_get_default(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)200 static int devlink_param_get_default(struct devlink *devlink,
201 const struct devlink_param *param,
202 struct devlink_param_gset_ctx *ctx,
203 struct netlink_ext_ack *extack)
204 {
205 if (!param->get_default)
206 return -EOPNOTSUPP;
207
208 return param->get_default(devlink, param->id, ctx, extack);
209 }
210
devlink_param_reset_default(struct devlink * devlink,const struct devlink_param * param,enum devlink_param_cmode cmode,struct netlink_ext_ack * extack)211 static int devlink_param_reset_default(struct devlink *devlink,
212 const struct devlink_param *param,
213 enum devlink_param_cmode cmode,
214 struct netlink_ext_ack *extack)
215 {
216 if (!param->reset_default)
217 return -EOPNOTSUPP;
218
219 return param->reset_default(devlink, param->id, cmode, extack);
220 }
221
222 static int
devlink_nl_param_value_put(struct sk_buff * msg,enum devlink_param_type type,int nla_type,union devlink_param_value * val,bool flag_as_u8)223 devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
224 int nla_type, union devlink_param_value *val,
225 bool flag_as_u8)
226 {
227 switch (type) {
228 case DEVLINK_PARAM_TYPE_U8:
229 if (nla_put_u8(msg, nla_type, val->vu8))
230 return -EMSGSIZE;
231 break;
232 case DEVLINK_PARAM_TYPE_U16:
233 if (nla_put_u16(msg, nla_type, val->vu16))
234 return -EMSGSIZE;
235 break;
236 case DEVLINK_PARAM_TYPE_U32:
237 if (nla_put_u32(msg, nla_type, val->vu32))
238 return -EMSGSIZE;
239 break;
240 case DEVLINK_PARAM_TYPE_U64:
241 if (devlink_nl_put_u64(msg, nla_type, val->vu64))
242 return -EMSGSIZE;
243 break;
244 case DEVLINK_PARAM_TYPE_STRING:
245 if (nla_put_string(msg, nla_type, val->vstr))
246 return -EMSGSIZE;
247 break;
248 case DEVLINK_PARAM_TYPE_BOOL:
249 /* default values of type bool are encoded with u8, so that
250 * false can be distinguished from not present
251 */
252 if (flag_as_u8) {
253 if (nla_put_u8(msg, nla_type, val->vbool))
254 return -EMSGSIZE;
255 } else {
256 if (val->vbool && nla_put_flag(msg, nla_type))
257 return -EMSGSIZE;
258 }
259 break;
260 case DEVLINK_PARAM_TYPE_U64_ARRAY:
261 if (val->u64arr.size > __DEVLINK_PARAM_MAX_ARRAY_SIZE)
262 return -EMSGSIZE;
263
264 for (int i = 0; i < val->u64arr.size; i++) {
265 if (nla_put_uint(msg, nla_type, val->u64arr.val[i]))
266 return -EMSGSIZE;
267 }
268 break;
269 }
270 return 0;
271 }
272
273 static int
devlink_nl_param_value_fill_one(struct sk_buff * msg,enum devlink_param_type type,enum devlink_param_cmode cmode,union devlink_param_value * val,union devlink_param_value * default_val,bool has_default)274 devlink_nl_param_value_fill_one(struct sk_buff *msg,
275 enum devlink_param_type type,
276 enum devlink_param_cmode cmode,
277 union devlink_param_value *val,
278 union devlink_param_value *default_val,
279 bool has_default)
280 {
281 struct nlattr *param_value_attr;
282 int err = -EMSGSIZE;
283
284 param_value_attr = nla_nest_start_noflag(msg,
285 DEVLINK_ATTR_PARAM_VALUE);
286 if (!param_value_attr)
287 return -EMSGSIZE;
288
289 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
290 goto value_nest_cancel;
291
292 err = devlink_nl_param_value_put(msg, type,
293 DEVLINK_ATTR_PARAM_VALUE_DATA,
294 val, false);
295 if (err)
296 goto value_nest_cancel;
297
298 if (has_default) {
299 err = devlink_nl_param_value_put(msg, type,
300 DEVLINK_ATTR_PARAM_VALUE_DEFAULT,
301 default_val, true);
302 if (err)
303 goto value_nest_cancel;
304 }
305
306 nla_nest_end(msg, param_value_attr);
307 return 0;
308
309 value_nest_cancel:
310 nla_nest_cancel(msg, param_value_attr);
311 return err;
312 }
313
devlink_nl_param_fill(struct sk_buff * msg,struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)314 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
315 unsigned int port_index,
316 struct devlink_param_item *param_item,
317 enum devlink_command cmd,
318 u32 portid, u32 seq, int flags,
319 struct netlink_ext_ack *extack)
320 {
321 bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
322 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
323 const struct devlink_param *param = param_item->param;
324 union devlink_param_value *default_value;
325 union devlink_param_value *param_value;
326 struct devlink_param_gset_ctx *ctx;
327 struct nlattr *param_values_list;
328 struct nlattr *param_attr;
329 void *hdr;
330 int err;
331 int i;
332
333 default_value = kzalloc_objs(*default_value,
334 DEVLINK_PARAM_CMODE_MAX + 1);
335 if (!default_value)
336 return -ENOMEM;
337
338 param_value = kzalloc_objs(*param_value, DEVLINK_PARAM_CMODE_MAX + 1);
339 if (!param_value) {
340 kfree(default_value);
341 return -ENOMEM;
342 }
343
344 ctx = kzalloc_obj(*ctx);
345 if (!ctx) {
346 kfree(param_value);
347 kfree(default_value);
348 return -ENOMEM;
349 }
350
351 /* Get value from driver part to driverinit configuration mode */
352 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
353 if (!devlink_param_cmode_is_supported(param, i))
354 continue;
355 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
356 if (param_item->driverinit_value_new_valid) {
357 param_value[i] = param_item->driverinit_value_new;
358 } else if (param_item->driverinit_value_valid) {
359 param_value[i] = param_item->driverinit_value;
360 } else {
361 err = -EOPNOTSUPP;
362 goto get_put_fail;
363 }
364
365 if (param_item->driverinit_value_valid) {
366 default_value[i] = param_item->driverinit_default;
367 default_value_set[i] = true;
368 }
369 } else {
370 ctx->cmode = i;
371 err = devlink_param_get(devlink, param, ctx, extack);
372 if (err)
373 goto get_put_fail;
374
375 param_value[i] = ctx->val;
376
377 err = devlink_param_get_default(devlink, param, ctx,
378 extack);
379 if (!err) {
380 default_value[i] = ctx->val;
381 default_value_set[i] = true;
382 } else if (err != -EOPNOTSUPP) {
383 goto get_put_fail;
384 }
385 }
386 param_value_set[i] = true;
387 }
388
389 err = -EMSGSIZE;
390 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
391 if (!hdr)
392 goto get_put_fail;
393
394 if (devlink_nl_put_handle(msg, devlink))
395 goto genlmsg_cancel;
396
397 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
398 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
399 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
400 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
401 goto genlmsg_cancel;
402
403 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
404 if (!param_attr)
405 goto genlmsg_cancel;
406 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
407 goto param_nest_cancel;
408 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
409 goto param_nest_cancel;
410 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, param->type))
411 goto param_nest_cancel;
412
413 param_values_list = nla_nest_start_noflag(msg,
414 DEVLINK_ATTR_PARAM_VALUES_LIST);
415 if (!param_values_list)
416 goto param_nest_cancel;
417
418 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
419 if (!param_value_set[i])
420 continue;
421 err = devlink_nl_param_value_fill_one(msg, param->type,
422 i, ¶m_value[i],
423 &default_value[i],
424 default_value_set[i]);
425 if (err)
426 goto values_list_nest_cancel;
427 }
428
429 nla_nest_end(msg, param_values_list);
430 nla_nest_end(msg, param_attr);
431 genlmsg_end(msg, hdr);
432 kfree(default_value);
433 kfree(param_value);
434 kfree(ctx);
435 return 0;
436
437 values_list_nest_cancel:
438 nla_nest_end(msg, param_values_list);
439 param_nest_cancel:
440 nla_nest_cancel(msg, param_attr);
441 genlmsg_cancel:
442 genlmsg_cancel(msg, hdr);
443 get_put_fail:
444 kfree(default_value);
445 kfree(param_value);
446 kfree(ctx);
447 return err;
448 }
449
devlink_param_notify(struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd)450 static void devlink_param_notify(struct devlink *devlink,
451 unsigned int port_index,
452 struct devlink_param_item *param_item,
453 enum devlink_command cmd)
454 {
455 struct sk_buff *msg;
456 int err;
457
458 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
459 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
460 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
461
462 /* devlink_notify_register() / devlink_notify_unregister()
463 * will replay the notifications if the params are added/removed
464 * outside of the lifetime of the instance.
465 */
466 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
467 return;
468
469 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
470 if (!msg)
471 return;
472 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
473 0, 0, 0, NULL);
474 if (err) {
475 nlmsg_free(msg);
476 return;
477 }
478
479 devlink_nl_notify_send(devlink, msg);
480 }
481
devlink_params_notify(struct devlink * devlink,enum devlink_command cmd)482 static void devlink_params_notify(struct devlink *devlink,
483 enum devlink_command cmd)
484 {
485 struct devlink_param_item *param_item;
486 unsigned long param_id;
487
488 xa_for_each(&devlink->params, param_id, param_item)
489 devlink_param_notify(devlink, 0, param_item, cmd);
490 }
491
devlink_params_notify_register(struct devlink * devlink)492 void devlink_params_notify_register(struct devlink *devlink)
493 {
494 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
495 }
496
devlink_params_notify_unregister(struct devlink * devlink)497 void devlink_params_notify_unregister(struct devlink *devlink)
498 {
499 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
500 }
501
devlink_nl_param_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)502 static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
503 struct devlink *devlink,
504 struct netlink_callback *cb,
505 int flags)
506 {
507 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
508 struct devlink_param_item *param_item;
509 unsigned long param_id;
510 int err = 0;
511
512 xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
513 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
514 DEVLINK_CMD_PARAM_GET,
515 NETLINK_CB(cb->skb).portid,
516 cb->nlh->nlmsg_seq, flags,
517 cb->extack);
518 if (err == -EOPNOTSUPP) {
519 err = 0;
520 } else if (err) {
521 state->idx = param_id;
522 break;
523 }
524 }
525
526 return err;
527 }
528
devlink_nl_param_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)529 int devlink_nl_param_get_dumpit(struct sk_buff *skb,
530 struct netlink_callback *cb)
531 {
532 return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
533 }
534
535 static int
devlink_param_type_get_from_info(struct genl_info * info,enum devlink_param_type * param_type)536 devlink_param_type_get_from_info(struct genl_info *info,
537 enum devlink_param_type *param_type)
538 {
539 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
540 return -EINVAL;
541
542 *param_type = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE]);
543
544 return 0;
545 }
546
547 static int
devlink_param_value_get_from_info(const struct devlink_param * param,struct genl_info * info,union devlink_param_value * value)548 devlink_param_value_get_from_info(const struct devlink_param *param,
549 struct genl_info *info,
550 union devlink_param_value *value)
551 {
552 struct nlattr *param_data;
553 int len, cnt, rem;
554
555 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
556
557 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
558 return -EINVAL;
559
560 switch (param->type) {
561 case DEVLINK_PARAM_TYPE_U8:
562 if (nla_len(param_data) != sizeof(u8))
563 return -EINVAL;
564 value->vu8 = nla_get_u8(param_data);
565 break;
566 case DEVLINK_PARAM_TYPE_U16:
567 if (nla_len(param_data) != sizeof(u16))
568 return -EINVAL;
569 value->vu16 = nla_get_u16(param_data);
570 break;
571 case DEVLINK_PARAM_TYPE_U32:
572 if (nla_len(param_data) != sizeof(u32))
573 return -EINVAL;
574 value->vu32 = nla_get_u32(param_data);
575 break;
576 case DEVLINK_PARAM_TYPE_U64:
577 if (nla_len(param_data) != sizeof(u64))
578 return -EINVAL;
579 value->vu64 = nla_get_u64(param_data);
580 break;
581 case DEVLINK_PARAM_TYPE_STRING:
582 len = strnlen(nla_data(param_data), nla_len(param_data));
583 if (len == nla_len(param_data) ||
584 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
585 return -EINVAL;
586 strcpy(value->vstr, nla_data(param_data));
587 break;
588 case DEVLINK_PARAM_TYPE_BOOL:
589 if (param_data && nla_len(param_data))
590 return -EINVAL;
591 value->vbool = nla_get_flag(param_data);
592 break;
593
594 case DEVLINK_PARAM_TYPE_U64_ARRAY:
595 cnt = 0;
596 nla_for_each_attr_type(param_data,
597 DEVLINK_ATTR_PARAM_VALUE_DATA,
598 genlmsg_data(info->genlhdr),
599 genlmsg_len(info->genlhdr), rem) {
600 if (cnt >= __DEVLINK_PARAM_MAX_ARRAY_SIZE)
601 return -EMSGSIZE;
602
603 if ((nla_len(param_data) != sizeof(u64)) &&
604 (nla_len(param_data) != sizeof(u32))) {
605 NL_SET_BAD_ATTR(info->extack, param_data);
606 return -EINVAL;
607 }
608
609 value->u64arr.val[cnt] = nla_get_uint(param_data);
610 cnt++;
611 }
612
613 value->u64arr.size = cnt;
614 break;
615 }
616 return 0;
617 }
618
619 static struct devlink_param_item *
devlink_param_get_from_info(struct xarray * params,struct genl_info * info)620 devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
621 {
622 char *param_name;
623
624 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
625 return NULL;
626
627 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
628 return devlink_param_find_by_name(params, param_name);
629 }
630
devlink_nl_param_get_doit(struct sk_buff * skb,struct genl_info * info)631 int devlink_nl_param_get_doit(struct sk_buff *skb,
632 struct genl_info *info)
633 {
634 struct devlink *devlink = devlink_nl_ctx(info)->devlink;
635 struct devlink_param_item *param_item;
636 struct sk_buff *msg;
637 int err;
638
639 param_item = devlink_param_get_from_info(&devlink->params, info);
640 if (!param_item)
641 return -EINVAL;
642
643 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
644 if (!msg)
645 return -ENOMEM;
646
647 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
648 DEVLINK_CMD_PARAM_GET, info->snd_portid,
649 info->snd_seq, 0, info->extack);
650 if (err) {
651 nlmsg_free(msg);
652 return err;
653 }
654
655 return genlmsg_reply(msg, info);
656 }
657
__devlink_nl_cmd_param_set_doit(struct devlink * devlink,unsigned int port_index,struct xarray * params,struct genl_info * info,enum devlink_command cmd)658 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
659 unsigned int port_index,
660 struct xarray *params,
661 struct genl_info *info,
662 enum devlink_command cmd)
663 {
664 enum devlink_param_type param_type;
665 struct devlink_param_gset_ctx ctx;
666 enum devlink_param_cmode cmode;
667 struct devlink_param_item *param_item;
668 const struct devlink_param *param;
669 union devlink_param_value value;
670 bool reset_default;
671 int err = 0;
672
673 param_item = devlink_param_get_from_info(params, info);
674 if (!param_item)
675 return -EINVAL;
676 param = param_item->param;
677 err = devlink_param_type_get_from_info(info, ¶m_type);
678 if (err)
679 return err;
680 if (param_type != param->type)
681 return -EINVAL;
682
683 reset_default = info->attrs[DEVLINK_ATTR_PARAM_RESET_DEFAULT];
684 if (!reset_default) {
685 err = devlink_param_value_get_from_info(param, info, &value);
686 if (err)
687 return err;
688 if (param->validate) {
689 err = param->validate(devlink, param->id, &value,
690 info->extack);
691 if (err)
692 return err;
693 }
694 }
695
696 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
697 return -EINVAL;
698 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
699 if (!devlink_param_cmode_is_supported(param, cmode))
700 return -EOPNOTSUPP;
701
702 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
703 if (reset_default) {
704 if (!param_item->driverinit_value_valid) {
705 NL_SET_ERR_MSG(info->extack,
706 "Default value not available");
707 return -EOPNOTSUPP;
708 }
709 value = param_item->driverinit_default;
710 }
711
712 param_item->driverinit_value_new = value;
713 param_item->driverinit_value_new_valid = true;
714 } else {
715 if (!param->set)
716 return -EOPNOTSUPP;
717 ctx.val = value;
718 ctx.cmode = cmode;
719 if (reset_default)
720 err = devlink_param_reset_default(devlink, param, cmode,
721 info->extack);
722 else
723 err = devlink_param_set(devlink, param, &ctx,
724 info->extack);
725 if (err)
726 return err;
727 }
728
729 devlink_param_notify(devlink, port_index, param_item, cmd);
730 return 0;
731 }
732
devlink_nl_param_set_doit(struct sk_buff * skb,struct genl_info * info)733 int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info)
734 {
735 struct devlink *devlink = devlink_nl_ctx(info)->devlink;
736
737 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
738 info, DEVLINK_CMD_PARAM_NEW);
739 }
740
devlink_nl_port_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)741 int devlink_nl_port_param_get_dumpit(struct sk_buff *msg,
742 struct netlink_callback *cb)
743 {
744 NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
745 return msg->len;
746 }
747
devlink_nl_port_param_get_doit(struct sk_buff * skb,struct genl_info * info)748 int devlink_nl_port_param_get_doit(struct sk_buff *skb,
749 struct genl_info *info)
750 {
751 NL_SET_ERR_MSG(info->extack, "Port params are not supported");
752 return -EINVAL;
753 }
754
devlink_nl_port_param_set_doit(struct sk_buff * skb,struct genl_info * info)755 int devlink_nl_port_param_set_doit(struct sk_buff *skb,
756 struct genl_info *info)
757 {
758 NL_SET_ERR_MSG(info->extack, "Port params are not supported");
759 return -EINVAL;
760 }
761
devlink_param_verify(const struct devlink_param * param)762 static int devlink_param_verify(const struct devlink_param *param)
763 {
764 if (!param || !param->name || !param->supported_cmodes)
765 return -EINVAL;
766 if (param->generic)
767 return devlink_param_generic_verify(param);
768 else
769 return devlink_param_driver_verify(param);
770 }
771
devlink_param_register(struct devlink * devlink,const struct devlink_param * param)772 static int devlink_param_register(struct devlink *devlink,
773 const struct devlink_param *param)
774 {
775 struct devlink_param_item *param_item;
776 int err;
777
778 WARN_ON(devlink_param_verify(param));
779 WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
780
781 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
782 WARN_ON(param->get || param->set);
783 else
784 WARN_ON(!param->get || !param->set);
785
786 param_item = kzalloc_obj(*param_item);
787 if (!param_item)
788 return -ENOMEM;
789
790 param_item->param = param;
791
792 err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
793 if (err)
794 goto err_xa_insert;
795
796 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
797 return 0;
798
799 err_xa_insert:
800 kfree(param_item);
801 return err;
802 }
803
devlink_param_unregister(struct devlink * devlink,const struct devlink_param * param)804 static void devlink_param_unregister(struct devlink *devlink,
805 const struct devlink_param *param)
806 {
807 struct devlink_param_item *param_item;
808
809 param_item = devlink_param_find_by_id(&devlink->params, param->id);
810 if (WARN_ON(!param_item))
811 return;
812 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
813 xa_erase(&devlink->params, param->id);
814 kfree(param_item);
815 }
816
817 /**
818 * devl_params_register - register configuration parameters
819 *
820 * @devlink: devlink
821 * @params: configuration parameters array
822 * @params_count: number of parameters provided
823 *
824 * Register the configuration parameters supported by the driver.
825 */
devl_params_register(struct devlink * devlink,const struct devlink_param * params,size_t params_count)826 int devl_params_register(struct devlink *devlink,
827 const struct devlink_param *params,
828 size_t params_count)
829 {
830 const struct devlink_param *param = params;
831 int i, err;
832
833 lockdep_assert_held(&devlink->lock);
834
835 for (i = 0; i < params_count; i++, param++) {
836 err = devlink_param_register(devlink, param);
837 if (err)
838 goto rollback;
839 }
840 return 0;
841
842 rollback:
843 if (!i)
844 return err;
845
846 for (param--; i > 0; i--, param--)
847 devlink_param_unregister(devlink, param);
848 return err;
849 }
850 EXPORT_SYMBOL_GPL(devl_params_register);
851
devlink_params_register(struct devlink * devlink,const struct devlink_param * params,size_t params_count)852 int devlink_params_register(struct devlink *devlink,
853 const struct devlink_param *params,
854 size_t params_count)
855 {
856 int err;
857
858 devl_lock(devlink);
859 err = devl_params_register(devlink, params, params_count);
860 devl_unlock(devlink);
861 return err;
862 }
863 EXPORT_SYMBOL_GPL(devlink_params_register);
864
865 /**
866 * devl_params_unregister - unregister configuration parameters
867 * @devlink: devlink
868 * @params: configuration parameters to unregister
869 * @params_count: number of parameters provided
870 */
devl_params_unregister(struct devlink * devlink,const struct devlink_param * params,size_t params_count)871 void devl_params_unregister(struct devlink *devlink,
872 const struct devlink_param *params,
873 size_t params_count)
874 {
875 const struct devlink_param *param = params;
876 int i;
877
878 lockdep_assert_held(&devlink->lock);
879
880 for (i = 0; i < params_count; i++, param++)
881 devlink_param_unregister(devlink, param);
882 }
883 EXPORT_SYMBOL_GPL(devl_params_unregister);
884
devlink_params_unregister(struct devlink * devlink,const struct devlink_param * params,size_t params_count)885 void devlink_params_unregister(struct devlink *devlink,
886 const struct devlink_param *params,
887 size_t params_count)
888 {
889 devl_lock(devlink);
890 devl_params_unregister(devlink, params, params_count);
891 devl_unlock(devlink);
892 }
893 EXPORT_SYMBOL_GPL(devlink_params_unregister);
894
895 /**
896 * devl_param_driverinit_value_get - get configuration parameter
897 * value for driver initializing
898 *
899 * @devlink: devlink
900 * @param_id: parameter ID
901 * @val: pointer to store the value of parameter in driverinit
902 * configuration mode
903 *
904 * This function should be used by the driver to get driverinit
905 * configuration for initialization after reload command.
906 *
907 * Note that lockless call of this function relies on the
908 * driver to maintain following basic sane behavior:
909 * 1) Driver ensures a call to this function cannot race with
910 * registering/unregistering the parameter with the same parameter ID.
911 * 2) Driver ensures a call to this function cannot race with
912 * devl_param_driverinit_value_set() call with the same parameter ID.
913 * 3) Driver ensures a call to this function cannot race with
914 * reload operation.
915 * If the driver is not able to comply, it has to take the devlink->lock
916 * while calling this.
917 */
devl_param_driverinit_value_get(struct devlink * devlink,u32 param_id,union devlink_param_value * val)918 int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
919 union devlink_param_value *val)
920 {
921 struct devlink_param_item *param_item;
922
923 if (WARN_ON(!devlink_reload_supported(devlink->ops)))
924 return -EOPNOTSUPP;
925
926 param_item = devlink_param_find_by_id(&devlink->params, param_id);
927 if (!param_item)
928 return -EINVAL;
929
930 if (!param_item->driverinit_value_valid)
931 return -EOPNOTSUPP;
932
933 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
934 DEVLINK_PARAM_CMODE_DRIVERINIT)))
935 return -EOPNOTSUPP;
936
937 *val = param_item->driverinit_value;
938
939 return 0;
940 }
941 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
942
943 /**
944 * devl_param_driverinit_value_set - set value of configuration
945 * parameter for driverinit
946 * configuration mode
947 *
948 * @devlink: devlink
949 * @param_id: parameter ID
950 * @init_val: value of parameter to set for driverinit configuration mode
951 *
952 * This function should be used by the driver to set driverinit
953 * configuration mode default value.
954 */
devl_param_driverinit_value_set(struct devlink * devlink,u32 param_id,union devlink_param_value * init_val)955 void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
956 union devlink_param_value *init_val)
957 {
958 struct devlink_param_item *param_item;
959
960 devl_assert_locked(devlink);
961
962 param_item = devlink_param_find_by_id(&devlink->params, param_id);
963 if (WARN_ON(!param_item))
964 return;
965
966 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
967 DEVLINK_PARAM_CMODE_DRIVERINIT)))
968 return;
969
970 param_item->driverinit_value = *init_val;
971 param_item->driverinit_value_valid = true;
972 param_item->driverinit_default = *init_val;
973
974 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
975 }
976 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
977
devlink_params_driverinit_load_new(struct devlink * devlink)978 void devlink_params_driverinit_load_new(struct devlink *devlink)
979 {
980 struct devlink_param_item *param_item;
981 unsigned long param_id;
982
983 xa_for_each(&devlink->params, param_id, param_item) {
984 if (!devlink_param_cmode_is_supported(param_item->param,
985 DEVLINK_PARAM_CMODE_DRIVERINIT) ||
986 !param_item->driverinit_value_new_valid)
987 continue;
988 param_item->driverinit_value = param_item->driverinit_value_new;
989 param_item->driverinit_value_valid = true;
990 param_item->driverinit_value_new_valid = false;
991 }
992 }
993
994 /**
995 * devl_param_value_changed - notify devlink on a parameter's value
996 * change. Should be called by the driver
997 * right after the change.
998 *
999 * @devlink: devlink
1000 * @param_id: parameter ID
1001 *
1002 * This function should be used by the driver to notify devlink on value
1003 * change, excluding driverinit configuration mode.
1004 * For driverinit configuration mode driver should use the function
1005 */
devl_param_value_changed(struct devlink * devlink,u32 param_id)1006 void devl_param_value_changed(struct devlink *devlink, u32 param_id)
1007 {
1008 struct devlink_param_item *param_item;
1009
1010 param_item = devlink_param_find_by_id(&devlink->params, param_id);
1011 WARN_ON(!param_item);
1012
1013 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
1014 }
1015 EXPORT_SYMBOL_GPL(devl_param_value_changed);
1016