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