xref: /linux/net/devlink/param.c (revision d103f26a5c8599385acb2d2e01dfbaedb00fdc0a)
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 
112 static int devlink_param_generic_verify(const struct devlink_param *param)
113 {
114 	/* verify it match generic parameter by id and name */
115 	if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
116 		return -EINVAL;
117 	if (strcmp(param->name, devlink_param_generic[param->id].name))
118 		return -ENOENT;
119 
120 	WARN_ON(param->type != devlink_param_generic[param->id].type);
121 
122 	return 0;
123 }
124 
125 static int devlink_param_driver_verify(const struct devlink_param *param)
126 {
127 	int i;
128 
129 	if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
130 		return -EINVAL;
131 	/* verify no such name in generic params */
132 	for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
133 		if (!strcmp(param->name, devlink_param_generic[i].name))
134 			return -EEXIST;
135 
136 	return 0;
137 }
138 
139 static struct devlink_param_item *
140 devlink_param_find_by_name(struct xarray *params, const char *param_name)
141 {
142 	struct devlink_param_item *param_item;
143 	unsigned long param_id;
144 
145 	xa_for_each(params, param_id, param_item) {
146 		if (!strcmp(param_item->param->name, param_name))
147 			return param_item;
148 	}
149 	return NULL;
150 }
151 
152 static struct devlink_param_item *
153 devlink_param_find_by_id(struct xarray *params, u32 param_id)
154 {
155 	return xa_load(params, param_id);
156 }
157 
158 static bool
159 devlink_param_cmode_is_supported(const struct devlink_param *param,
160 				 enum devlink_param_cmode cmode)
161 {
162 	return test_bit(cmode, &param->supported_cmodes);
163 }
164 
165 static int devlink_param_get(struct devlink *devlink,
166 			     const struct devlink_param *param,
167 			     struct devlink_param_gset_ctx *ctx)
168 {
169 	if (!param->get)
170 		return -EOPNOTSUPP;
171 	return param->get(devlink, param->id, ctx);
172 }
173 
174 static int devlink_param_set(struct devlink *devlink,
175 			     const struct devlink_param *param,
176 			     struct devlink_param_gset_ctx *ctx,
177 			     struct netlink_ext_ack *extack)
178 {
179 	if (!param->set)
180 		return -EOPNOTSUPP;
181 	return param->set(devlink, param->id, ctx, extack);
182 }
183 
184 static int
185 devlink_nl_param_value_fill_one(struct sk_buff *msg,
186 				enum devlink_param_type type,
187 				enum devlink_param_cmode cmode,
188 				union devlink_param_value val)
189 {
190 	struct nlattr *param_value_attr;
191 
192 	param_value_attr = nla_nest_start_noflag(msg,
193 						 DEVLINK_ATTR_PARAM_VALUE);
194 	if (!param_value_attr)
195 		goto nla_put_failure;
196 
197 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
198 		goto value_nest_cancel;
199 
200 	switch (type) {
201 	case DEVLINK_PARAM_TYPE_U8:
202 		if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
203 			goto value_nest_cancel;
204 		break;
205 	case DEVLINK_PARAM_TYPE_U16:
206 		if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
207 			goto value_nest_cancel;
208 		break;
209 	case DEVLINK_PARAM_TYPE_U32:
210 		if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
211 			goto value_nest_cancel;
212 		break;
213 	case DEVLINK_PARAM_TYPE_U64:
214 		if (devlink_nl_put_u64(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
215 				       val.vu64))
216 			goto value_nest_cancel;
217 		break;
218 	case DEVLINK_PARAM_TYPE_STRING:
219 		if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
220 				   val.vstr))
221 			goto value_nest_cancel;
222 		break;
223 	case DEVLINK_PARAM_TYPE_BOOL:
224 		if (val.vbool &&
225 		    nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
226 			goto value_nest_cancel;
227 		break;
228 	}
229 
230 	nla_nest_end(msg, param_value_attr);
231 	return 0;
232 
233 value_nest_cancel:
234 	nla_nest_cancel(msg, param_value_attr);
235 nla_put_failure:
236 	return -EMSGSIZE;
237 }
238 
239 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
240 				 unsigned int port_index,
241 				 struct devlink_param_item *param_item,
242 				 enum devlink_command cmd,
243 				 u32 portid, u32 seq, int flags)
244 {
245 	union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
246 	bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
247 	const struct devlink_param *param = param_item->param;
248 	struct devlink_param_gset_ctx ctx;
249 	struct nlattr *param_values_list;
250 	struct nlattr *param_attr;
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 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, param->type))
297 		goto param_nest_cancel;
298 
299 	param_values_list = nla_nest_start_noflag(msg,
300 						  DEVLINK_ATTR_PARAM_VALUES_LIST);
301 	if (!param_values_list)
302 		goto param_nest_cancel;
303 
304 	for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
305 		if (!param_value_set[i])
306 			continue;
307 		err = devlink_nl_param_value_fill_one(msg, param->type,
308 						      i, param_value[i]);
309 		if (err)
310 			goto values_list_nest_cancel;
311 	}
312 
313 	nla_nest_end(msg, param_values_list);
314 	nla_nest_end(msg, param_attr);
315 	genlmsg_end(msg, hdr);
316 	return 0;
317 
318 values_list_nest_cancel:
319 	nla_nest_end(msg, param_values_list);
320 param_nest_cancel:
321 	nla_nest_cancel(msg, param_attr);
322 genlmsg_cancel:
323 	genlmsg_cancel(msg, hdr);
324 	return -EMSGSIZE;
325 }
326 
327 static void devlink_param_notify(struct devlink *devlink,
328 				 unsigned int port_index,
329 				 struct devlink_param_item *param_item,
330 				 enum devlink_command cmd)
331 {
332 	struct sk_buff *msg;
333 	int err;
334 
335 	WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
336 		cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
337 		cmd != DEVLINK_CMD_PORT_PARAM_DEL);
338 
339 	/* devlink_notify_register() / devlink_notify_unregister()
340 	 * will replay the notifications if the params are added/removed
341 	 * outside of the lifetime of the instance.
342 	 */
343 	if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
344 		return;
345 
346 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
347 	if (!msg)
348 		return;
349 	err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
350 				    0, 0, 0);
351 	if (err) {
352 		nlmsg_free(msg);
353 		return;
354 	}
355 
356 	devlink_nl_notify_send(devlink, msg);
357 }
358 
359 static void devlink_params_notify(struct devlink *devlink,
360 				  enum devlink_command cmd)
361 {
362 	struct devlink_param_item *param_item;
363 	unsigned long param_id;
364 
365 	xa_for_each(&devlink->params, param_id, param_item)
366 		devlink_param_notify(devlink, 0, param_item, cmd);
367 }
368 
369 void devlink_params_notify_register(struct devlink *devlink)
370 {
371 	devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
372 }
373 
374 void devlink_params_notify_unregister(struct devlink *devlink)
375 {
376 	devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
377 }
378 
379 static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
380 					 struct devlink *devlink,
381 					 struct netlink_callback *cb,
382 					 int flags)
383 {
384 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
385 	struct devlink_param_item *param_item;
386 	unsigned long param_id;
387 	int err = 0;
388 
389 	xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
390 		err = devlink_nl_param_fill(msg, devlink, 0, param_item,
391 					    DEVLINK_CMD_PARAM_GET,
392 					    NETLINK_CB(cb->skb).portid,
393 					    cb->nlh->nlmsg_seq, flags);
394 		if (err == -EOPNOTSUPP) {
395 			err = 0;
396 		} else if (err) {
397 			state->idx = param_id;
398 			break;
399 		}
400 	}
401 
402 	return err;
403 }
404 
405 int devlink_nl_param_get_dumpit(struct sk_buff *skb,
406 				struct netlink_callback *cb)
407 {
408 	return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
409 }
410 
411 static int
412 devlink_param_type_get_from_info(struct genl_info *info,
413 				 enum devlink_param_type *param_type)
414 {
415 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
416 		return -EINVAL;
417 
418 	*param_type = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE]);
419 
420 	return 0;
421 }
422 
423 static int
424 devlink_param_value_get_from_info(const struct devlink_param *param,
425 				  struct genl_info *info,
426 				  union devlink_param_value *value)
427 {
428 	struct nlattr *param_data;
429 	int len;
430 
431 	param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
432 
433 	if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
434 		return -EINVAL;
435 
436 	switch (param->type) {
437 	case DEVLINK_PARAM_TYPE_U8:
438 		if (nla_len(param_data) != sizeof(u8))
439 			return -EINVAL;
440 		value->vu8 = nla_get_u8(param_data);
441 		break;
442 	case DEVLINK_PARAM_TYPE_U16:
443 		if (nla_len(param_data) != sizeof(u16))
444 			return -EINVAL;
445 		value->vu16 = nla_get_u16(param_data);
446 		break;
447 	case DEVLINK_PARAM_TYPE_U32:
448 		if (nla_len(param_data) != sizeof(u32))
449 			return -EINVAL;
450 		value->vu32 = nla_get_u32(param_data);
451 		break;
452 	case DEVLINK_PARAM_TYPE_U64:
453 		if (nla_len(param_data) != sizeof(u64))
454 			return -EINVAL;
455 		value->vu64 = nla_get_u64(param_data);
456 		break;
457 	case DEVLINK_PARAM_TYPE_STRING:
458 		len = strnlen(nla_data(param_data), nla_len(param_data));
459 		if (len == nla_len(param_data) ||
460 		    len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
461 			return -EINVAL;
462 		strcpy(value->vstr, nla_data(param_data));
463 		break;
464 	case DEVLINK_PARAM_TYPE_BOOL:
465 		if (param_data && nla_len(param_data))
466 			return -EINVAL;
467 		value->vbool = nla_get_flag(param_data);
468 		break;
469 	}
470 	return 0;
471 }
472 
473 static struct devlink_param_item *
474 devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
475 {
476 	char *param_name;
477 
478 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
479 		return NULL;
480 
481 	param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
482 	return devlink_param_find_by_name(params, param_name);
483 }
484 
485 int devlink_nl_param_get_doit(struct sk_buff *skb,
486 			      struct genl_info *info)
487 {
488 	struct devlink *devlink = info->user_ptr[0];
489 	struct devlink_param_item *param_item;
490 	struct sk_buff *msg;
491 	int err;
492 
493 	param_item = devlink_param_get_from_info(&devlink->params, info);
494 	if (!param_item)
495 		return -EINVAL;
496 
497 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
498 	if (!msg)
499 		return -ENOMEM;
500 
501 	err = devlink_nl_param_fill(msg, devlink, 0, param_item,
502 				    DEVLINK_CMD_PARAM_GET,
503 				    info->snd_portid, info->snd_seq, 0);
504 	if (err) {
505 		nlmsg_free(msg);
506 		return err;
507 	}
508 
509 	return genlmsg_reply(msg, info);
510 }
511 
512 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
513 					   unsigned int port_index,
514 					   struct xarray *params,
515 					   struct genl_info *info,
516 					   enum devlink_command cmd)
517 {
518 	enum devlink_param_type param_type;
519 	struct devlink_param_gset_ctx ctx;
520 	enum devlink_param_cmode cmode;
521 	struct devlink_param_item *param_item;
522 	const struct devlink_param *param;
523 	union devlink_param_value value;
524 	int err = 0;
525 
526 	param_item = devlink_param_get_from_info(params, info);
527 	if (!param_item)
528 		return -EINVAL;
529 	param = param_item->param;
530 	err = devlink_param_type_get_from_info(info, &param_type);
531 	if (err)
532 		return err;
533 	if (param_type != param->type)
534 		return -EINVAL;
535 	err = devlink_param_value_get_from_info(param, info, &value);
536 	if (err)
537 		return err;
538 	if (param->validate) {
539 		err = param->validate(devlink, param->id, value, info->extack);
540 		if (err)
541 			return err;
542 	}
543 
544 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
545 		return -EINVAL;
546 	cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
547 	if (!devlink_param_cmode_is_supported(param, cmode))
548 		return -EOPNOTSUPP;
549 
550 	if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
551 		param_item->driverinit_value_new = value;
552 		param_item->driverinit_value_new_valid = true;
553 	} else {
554 		if (!param->set)
555 			return -EOPNOTSUPP;
556 		ctx.val = value;
557 		ctx.cmode = cmode;
558 		err = devlink_param_set(devlink, param, &ctx, info->extack);
559 		if (err)
560 			return err;
561 	}
562 
563 	devlink_param_notify(devlink, port_index, param_item, cmd);
564 	return 0;
565 }
566 
567 int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info)
568 {
569 	struct devlink *devlink = info->user_ptr[0];
570 
571 	return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
572 					       info, DEVLINK_CMD_PARAM_NEW);
573 }
574 
575 int devlink_nl_port_param_get_dumpit(struct sk_buff *msg,
576 				     struct netlink_callback *cb)
577 {
578 	NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
579 	return msg->len;
580 }
581 
582 int devlink_nl_port_param_get_doit(struct sk_buff *skb,
583 				   struct genl_info *info)
584 {
585 	NL_SET_ERR_MSG(info->extack, "Port params are not supported");
586 	return -EINVAL;
587 }
588 
589 int devlink_nl_port_param_set_doit(struct sk_buff *skb,
590 				   struct genl_info *info)
591 {
592 	NL_SET_ERR_MSG(info->extack, "Port params are not supported");
593 	return -EINVAL;
594 }
595 
596 static int devlink_param_verify(const struct devlink_param *param)
597 {
598 	if (!param || !param->name || !param->supported_cmodes)
599 		return -EINVAL;
600 	if (param->generic)
601 		return devlink_param_generic_verify(param);
602 	else
603 		return devlink_param_driver_verify(param);
604 }
605 
606 static int devlink_param_register(struct devlink *devlink,
607 				  const struct devlink_param *param)
608 {
609 	struct devlink_param_item *param_item;
610 	int err;
611 
612 	WARN_ON(devlink_param_verify(param));
613 	WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
614 
615 	if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
616 		WARN_ON(param->get || param->set);
617 	else
618 		WARN_ON(!param->get || !param->set);
619 
620 	param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
621 	if (!param_item)
622 		return -ENOMEM;
623 
624 	param_item->param = param;
625 
626 	err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
627 	if (err)
628 		goto err_xa_insert;
629 
630 	devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
631 	return 0;
632 
633 err_xa_insert:
634 	kfree(param_item);
635 	return err;
636 }
637 
638 static void devlink_param_unregister(struct devlink *devlink,
639 				     const struct devlink_param *param)
640 {
641 	struct devlink_param_item *param_item;
642 
643 	param_item = devlink_param_find_by_id(&devlink->params, param->id);
644 	if (WARN_ON(!param_item))
645 		return;
646 	devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
647 	xa_erase(&devlink->params, param->id);
648 	kfree(param_item);
649 }
650 
651 /**
652  *	devl_params_register - register configuration parameters
653  *
654  *	@devlink: devlink
655  *	@params: configuration parameters array
656  *	@params_count: number of parameters provided
657  *
658  *	Register the configuration parameters supported by the driver.
659  */
660 int devl_params_register(struct devlink *devlink,
661 			 const struct devlink_param *params,
662 			 size_t params_count)
663 {
664 	const struct devlink_param *param = params;
665 	int i, err;
666 
667 	lockdep_assert_held(&devlink->lock);
668 
669 	for (i = 0; i < params_count; i++, param++) {
670 		err = devlink_param_register(devlink, param);
671 		if (err)
672 			goto rollback;
673 	}
674 	return 0;
675 
676 rollback:
677 	if (!i)
678 		return err;
679 
680 	for (param--; i > 0; i--, param--)
681 		devlink_param_unregister(devlink, param);
682 	return err;
683 }
684 EXPORT_SYMBOL_GPL(devl_params_register);
685 
686 int devlink_params_register(struct devlink *devlink,
687 			    const struct devlink_param *params,
688 			    size_t params_count)
689 {
690 	int err;
691 
692 	devl_lock(devlink);
693 	err = devl_params_register(devlink, params, params_count);
694 	devl_unlock(devlink);
695 	return err;
696 }
697 EXPORT_SYMBOL_GPL(devlink_params_register);
698 
699 /**
700  *	devl_params_unregister - unregister configuration parameters
701  *	@devlink: devlink
702  *	@params: configuration parameters to unregister
703  *	@params_count: number of parameters provided
704  */
705 void devl_params_unregister(struct devlink *devlink,
706 			    const struct devlink_param *params,
707 			    size_t params_count)
708 {
709 	const struct devlink_param *param = params;
710 	int i;
711 
712 	lockdep_assert_held(&devlink->lock);
713 
714 	for (i = 0; i < params_count; i++, param++)
715 		devlink_param_unregister(devlink, param);
716 }
717 EXPORT_SYMBOL_GPL(devl_params_unregister);
718 
719 void devlink_params_unregister(struct devlink *devlink,
720 			       const struct devlink_param *params,
721 			       size_t params_count)
722 {
723 	devl_lock(devlink);
724 	devl_params_unregister(devlink, params, params_count);
725 	devl_unlock(devlink);
726 }
727 EXPORT_SYMBOL_GPL(devlink_params_unregister);
728 
729 /**
730  *	devl_param_driverinit_value_get - get configuration parameter
731  *					  value for driver initializing
732  *
733  *	@devlink: devlink
734  *	@param_id: parameter ID
735  *	@val: pointer to store the value of parameter in driverinit
736  *	      configuration mode
737  *
738  *	This function should be used by the driver to get driverinit
739  *	configuration for initialization after reload command.
740  *
741  *	Note that lockless call of this function relies on the
742  *	driver to maintain following basic sane behavior:
743  *	1) Driver ensures a call to this function cannot race with
744  *	   registering/unregistering the parameter with the same parameter ID.
745  *	2) Driver ensures a call to this function cannot race with
746  *	   devl_param_driverinit_value_set() call with the same parameter ID.
747  *	3) Driver ensures a call to this function cannot race with
748  *	   reload operation.
749  *	If the driver is not able to comply, it has to take the devlink->lock
750  *	while calling this.
751  */
752 int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
753 				    union devlink_param_value *val)
754 {
755 	struct devlink_param_item *param_item;
756 
757 	if (WARN_ON(!devlink_reload_supported(devlink->ops)))
758 		return -EOPNOTSUPP;
759 
760 	param_item = devlink_param_find_by_id(&devlink->params, param_id);
761 	if (!param_item)
762 		return -EINVAL;
763 
764 	if (!param_item->driverinit_value_valid)
765 		return -EOPNOTSUPP;
766 
767 	if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
768 						      DEVLINK_PARAM_CMODE_DRIVERINIT)))
769 		return -EOPNOTSUPP;
770 
771 	*val = param_item->driverinit_value;
772 
773 	return 0;
774 }
775 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
776 
777 /**
778  *	devl_param_driverinit_value_set - set value of configuration
779  *					  parameter for driverinit
780  *					  configuration mode
781  *
782  *	@devlink: devlink
783  *	@param_id: parameter ID
784  *	@init_val: value of parameter to set for driverinit configuration mode
785  *
786  *	This function should be used by the driver to set driverinit
787  *	configuration mode default value.
788  */
789 void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
790 				     union devlink_param_value init_val)
791 {
792 	struct devlink_param_item *param_item;
793 
794 	devl_assert_locked(devlink);
795 
796 	param_item = devlink_param_find_by_id(&devlink->params, param_id);
797 	if (WARN_ON(!param_item))
798 		return;
799 
800 	if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
801 						      DEVLINK_PARAM_CMODE_DRIVERINIT)))
802 		return;
803 
804 	param_item->driverinit_value = init_val;
805 	param_item->driverinit_value_valid = true;
806 
807 	devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
808 }
809 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
810 
811 void devlink_params_driverinit_load_new(struct devlink *devlink)
812 {
813 	struct devlink_param_item *param_item;
814 	unsigned long param_id;
815 
816 	xa_for_each(&devlink->params, param_id, param_item) {
817 		if (!devlink_param_cmode_is_supported(param_item->param,
818 						      DEVLINK_PARAM_CMODE_DRIVERINIT) ||
819 		    !param_item->driverinit_value_new_valid)
820 			continue;
821 		param_item->driverinit_value = param_item->driverinit_value_new;
822 		param_item->driverinit_value_valid = true;
823 		param_item->driverinit_value_new_valid = false;
824 	}
825 }
826 
827 /**
828  *	devl_param_value_changed - notify devlink on a parameter's value
829  *				   change. Should be called by the driver
830  *				   right after the change.
831  *
832  *	@devlink: devlink
833  *	@param_id: parameter ID
834  *
835  *	This function should be used by the driver to notify devlink on value
836  *	change, excluding driverinit configuration mode.
837  *	For driverinit configuration mode driver should use the function
838  */
839 void devl_param_value_changed(struct devlink *devlink, u32 param_id)
840 {
841 	struct devlink_param_item *param_item;
842 
843 	param_item = devlink_param_find_by_id(&devlink->params, param_id);
844 	WARN_ON(!param_item);
845 
846 	devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
847 }
848 EXPORT_SYMBOL_GPL(devl_param_value_changed);
849