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