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