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