1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies */
3 
4 #include <devlink.h>
5 
6 #include "mlx5_core.h"
7 #include "fw_reset.h"
8 #include "fs_core.h"
9 #include "eswitch.h"
10 #include "lag/lag.h"
11 #include "esw/qos.h"
12 #include "sf/dev/dev.h"
13 #include "sf/sf.h"
14 
15 static int mlx5_devlink_flash_update(struct devlink *devlink,
16 				     struct devlink_flash_update_params *params,
17 				     struct netlink_ext_ack *extack)
18 {
19 	struct mlx5_core_dev *dev = devlink_priv(devlink);
20 
21 	return mlx5_firmware_flash(dev, params->fw, extack);
22 }
23 
24 static u8 mlx5_fw_ver_major(u32 version)
25 {
26 	return (version >> 24) & 0xff;
27 }
28 
29 static u8 mlx5_fw_ver_minor(u32 version)
30 {
31 	return (version >> 16) & 0xff;
32 }
33 
34 static u16 mlx5_fw_ver_subminor(u32 version)
35 {
36 	return version & 0xffff;
37 }
38 
39 #define DEVLINK_FW_STRING_LEN 32
40 
41 static int
42 mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
43 		      struct netlink_ext_ack *extack)
44 {
45 	struct mlx5_core_dev *dev = devlink_priv(devlink);
46 	char version_str[DEVLINK_FW_STRING_LEN];
47 	u32 running_fw, stored_fw;
48 	int err;
49 
50 	err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id);
51 	if (err)
52 		return err;
53 
54 	err = mlx5_fw_version_query(dev, &running_fw, &stored_fw);
55 	if (err)
56 		return err;
57 
58 	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
59 		 mlx5_fw_ver_major(running_fw), mlx5_fw_ver_minor(running_fw),
60 		 mlx5_fw_ver_subminor(running_fw));
61 	err = devlink_info_version_running_put(req, "fw.version", version_str);
62 	if (err)
63 		return err;
64 	err = devlink_info_version_running_put(req,
65 					       DEVLINK_INFO_VERSION_GENERIC_FW,
66 					       version_str);
67 	if (err)
68 		return err;
69 
70 	/* no pending version, return running (stored) version */
71 	if (stored_fw == 0)
72 		stored_fw = running_fw;
73 
74 	snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
75 		 mlx5_fw_ver_major(stored_fw), mlx5_fw_ver_minor(stored_fw),
76 		 mlx5_fw_ver_subminor(stored_fw));
77 	err = devlink_info_version_stored_put(req, "fw.version", version_str);
78 	if (err)
79 		return err;
80 	return devlink_info_version_stored_put(req,
81 					       DEVLINK_INFO_VERSION_GENERIC_FW,
82 					       version_str);
83 }
84 
85 static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netlink_ext_ack *extack)
86 {
87 	struct mlx5_core_dev *dev = devlink_priv(devlink);
88 	u8 reset_level, reset_type, net_port_alive;
89 	int err;
90 
91 	err = mlx5_fw_reset_query(dev, &reset_level, &reset_type);
92 	if (err)
93 		return err;
94 	if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL3)) {
95 		NL_SET_ERR_MSG_MOD(extack, "FW activate requires reboot");
96 		return -EINVAL;
97 	}
98 
99 	net_port_alive = !!(reset_type & MLX5_MFRL_REG_RESET_TYPE_NET_PORT_ALIVE);
100 	err = mlx5_fw_reset_set_reset_sync(dev, net_port_alive, extack);
101 	if (err)
102 		return err;
103 
104 	err = mlx5_fw_reset_wait_reset_done(dev);
105 	if (err)
106 		return err;
107 
108 	mlx5_unload_one_devl_locked(dev, true);
109 	err = mlx5_health_wait_pci_up(dev);
110 	if (err)
111 		NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset");
112 
113 	return err;
114 }
115 
116 static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink,
117 					      struct netlink_ext_ack *extack)
118 {
119 	struct mlx5_core_dev *dev = devlink_priv(devlink);
120 	u8 reset_level;
121 	int err;
122 
123 	err = mlx5_fw_reset_query(dev, &reset_level, NULL);
124 	if (err)
125 		return err;
126 	if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) {
127 		NL_SET_ERR_MSG_MOD(extack,
128 				   "FW upgrade to the stored FW can't be done by FW live patching");
129 		return -EINVAL;
130 	}
131 
132 	return mlx5_fw_reset_set_live_patch(dev);
133 }
134 
135 static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
136 				    enum devlink_reload_action action,
137 				    enum devlink_reload_limit limit,
138 				    struct netlink_ext_ack *extack)
139 {
140 	struct mlx5_core_dev *dev = devlink_priv(devlink);
141 	struct pci_dev *pdev = dev->pdev;
142 	bool sf_dev_allocated;
143 	int ret = 0;
144 
145 	sf_dev_allocated = mlx5_sf_dev_allocated(dev);
146 	if (sf_dev_allocated) {
147 		/* Reload results in deleting SF device which further results in
148 		 * unregistering devlink instance while holding devlink_mutext.
149 		 * Hence, do not support reload.
150 		 */
151 		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported when SFs are allocated");
152 		return -EOPNOTSUPP;
153 	}
154 
155 	if (mlx5_lag_is_active(dev)) {
156 		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode");
157 		return -EOPNOTSUPP;
158 	}
159 
160 	if (mlx5_core_is_mp_slave(dev)) {
161 		NL_SET_ERR_MSG_MOD(extack, "reload is unsupported for multi port slave");
162 		return -EOPNOTSUPP;
163 	}
164 
165 	if (pci_num_vf(pdev)) {
166 		NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
167 	}
168 
169 	switch (action) {
170 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
171 		mlx5_unload_one_devl_locked(dev, false);
172 		break;
173 	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
174 		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
175 			ret = mlx5_devlink_trigger_fw_live_patch(devlink, extack);
176 		else
177 			ret = mlx5_devlink_reload_fw_activate(devlink, extack);
178 		break;
179 	default:
180 		/* Unsupported action should not get to this function */
181 		WARN_ON(1);
182 		ret = -EOPNOTSUPP;
183 	}
184 
185 	return ret;
186 }
187 
188 static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
189 				  enum devlink_reload_limit limit, u32 *actions_performed,
190 				  struct netlink_ext_ack *extack)
191 {
192 	struct mlx5_core_dev *dev = devlink_priv(devlink);
193 	int ret = 0;
194 
195 	*actions_performed = BIT(action);
196 	switch (action) {
197 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
198 		ret = mlx5_load_one_devl_locked(dev, false);
199 		break;
200 	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
201 		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
202 			break;
203 		/* On fw_activate action, also driver is reloaded and reinit performed */
204 		*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
205 		ret = mlx5_load_one_devl_locked(dev, false);
206 		break;
207 	default:
208 		/* Unsupported action should not get to this function */
209 		WARN_ON(1);
210 		ret = -EOPNOTSUPP;
211 	}
212 
213 	return ret;
214 }
215 
216 static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id)
217 {
218 	struct mlx5_devlink_trap *dl_trap;
219 
220 	list_for_each_entry(dl_trap, &dev->priv.traps, list)
221 		if (dl_trap->trap.id == trap_id)
222 			return dl_trap;
223 
224 	return NULL;
225 }
226 
227 static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap,
228 				  void *trap_ctx)
229 {
230 	struct mlx5_core_dev *dev = devlink_priv(devlink);
231 	struct mlx5_devlink_trap *dl_trap;
232 
233 	dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL);
234 	if (!dl_trap)
235 		return -ENOMEM;
236 
237 	dl_trap->trap.id = trap->id;
238 	dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP;
239 	dl_trap->item = trap_ctx;
240 
241 	if (mlx5_find_trap_by_id(dev, trap->id)) {
242 		kfree(dl_trap);
243 		mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id);
244 		return -EEXIST;
245 	}
246 
247 	list_add_tail(&dl_trap->list, &dev->priv.traps);
248 	return 0;
249 }
250 
251 static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap,
252 				   void *trap_ctx)
253 {
254 	struct mlx5_core_dev *dev = devlink_priv(devlink);
255 	struct mlx5_devlink_trap *dl_trap;
256 
257 	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
258 	if (!dl_trap) {
259 		mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id);
260 		return;
261 	}
262 	list_del(&dl_trap->list);
263 	kfree(dl_trap);
264 }
265 
266 static int mlx5_devlink_trap_action_set(struct devlink *devlink,
267 					const struct devlink_trap *trap,
268 					enum devlink_trap_action action,
269 					struct netlink_ext_ack *extack)
270 {
271 	struct mlx5_core_dev *dev = devlink_priv(devlink);
272 	struct mlx5_devlink_trap_event_ctx trap_event_ctx;
273 	enum devlink_trap_action action_orig;
274 	struct mlx5_devlink_trap *dl_trap;
275 	int err;
276 
277 	if (is_mdev_switchdev_mode(dev)) {
278 		NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode");
279 		return -EOPNOTSUPP;
280 	}
281 
282 	dl_trap = mlx5_find_trap_by_id(dev, trap->id);
283 	if (!dl_trap) {
284 		mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id);
285 		return -EINVAL;
286 	}
287 
288 	if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP)
289 		return -EOPNOTSUPP;
290 
291 	if (action == dl_trap->trap.action)
292 		return 0;
293 
294 	action_orig = dl_trap->trap.action;
295 	dl_trap->trap.action = action;
296 	trap_event_ctx.trap = &dl_trap->trap;
297 	trap_event_ctx.err = 0;
298 	err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP,
299 						&trap_event_ctx);
300 	if (err == NOTIFY_BAD)
301 		dl_trap->trap.action = action_orig;
302 
303 	return trap_event_ctx.err;
304 }
305 
306 static const struct devlink_ops mlx5_devlink_ops = {
307 #ifdef CONFIG_MLX5_ESWITCH
308 	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
309 	.eswitch_mode_get = mlx5_devlink_eswitch_mode_get,
310 	.eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set,
311 	.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
312 	.eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set,
313 	.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
314 	.port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get,
315 	.port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set,
316 	.rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set,
317 	.rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set,
318 	.rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set,
319 	.rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set,
320 	.rate_node_new = mlx5_esw_devlink_rate_node_new,
321 	.rate_node_del = mlx5_esw_devlink_rate_node_del,
322 	.rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
323 	.port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
324 	.port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
325 	.port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
326 	.port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
327 #endif
328 #ifdef CONFIG_MLX5_SF_MANAGER
329 	.port_new = mlx5_devlink_sf_port_new,
330 	.port_del = mlx5_devlink_sf_port_del,
331 	.port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
332 	.port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
333 #endif
334 	.flash_update = mlx5_devlink_flash_update,
335 	.info_get = mlx5_devlink_info_get,
336 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
337 			  BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
338 	.reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
339 	.reload_down = mlx5_devlink_reload_down,
340 	.reload_up = mlx5_devlink_reload_up,
341 	.trap_init = mlx5_devlink_trap_init,
342 	.trap_fini = mlx5_devlink_trap_fini,
343 	.trap_action_set = mlx5_devlink_trap_action_set,
344 };
345 
346 void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb,
347 			      struct devlink_port *dl_port)
348 {
349 	struct devlink *devlink = priv_to_devlink(dev);
350 	struct mlx5_devlink_trap *dl_trap;
351 
352 	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
353 	if (!dl_trap) {
354 		mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id);
355 		return;
356 	}
357 
358 	if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) {
359 		mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id,
360 			      dl_trap->trap.action);
361 		return;
362 	}
363 	devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL);
364 }
365 
366 int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev)
367 {
368 	struct mlx5_devlink_trap *dl_trap;
369 	int count = 0;
370 
371 	list_for_each_entry(dl_trap, &dev->priv.traps, list)
372 		if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP)
373 			count++;
374 
375 	return count;
376 }
377 
378 int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id,
379 				  enum devlink_trap_action *action)
380 {
381 	struct mlx5_devlink_trap *dl_trap;
382 
383 	dl_trap = mlx5_find_trap_by_id(dev, trap_id);
384 	if (!dl_trap) {
385 		mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x",
386 			      trap_id);
387 		return -EINVAL;
388 	}
389 
390 	*action = dl_trap->trap.action;
391 	return 0;
392 }
393 
394 struct devlink *mlx5_devlink_alloc(struct device *dev)
395 {
396 	return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev),
397 			     dev);
398 }
399 
400 void mlx5_devlink_free(struct devlink *devlink)
401 {
402 	devlink_free(devlink);
403 }
404 
405 static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
406 					     union devlink_param_value val,
407 					     struct netlink_ext_ack *extack)
408 {
409 	struct mlx5_core_dev *dev = devlink_priv(devlink);
410 	bool new_state = val.vbool;
411 
412 	if (new_state && !MLX5_CAP_GEN(dev, roce) &&
413 	    !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) {
414 		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
415 		return -EOPNOTSUPP;
416 	}
417 	if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) {
418 		NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE");
419 		return -EOPNOTSUPP;
420 	}
421 
422 	return 0;
423 }
424 
425 #ifdef CONFIG_MLX5_ESWITCH
426 static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id,
427 						 union devlink_param_value val,
428 						 struct netlink_ext_ack *extack)
429 {
430 	int group_num = val.vu32;
431 
432 	if (group_num < 1 || group_num > 1024) {
433 		NL_SET_ERR_MSG_MOD(extack,
434 				   "Unsupported group number, supported range is 1-1024");
435 		return -EOPNOTSUPP;
436 	}
437 
438 	return 0;
439 }
440 
441 static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
442 					  struct devlink_param_gset_ctx *ctx)
443 {
444 	struct mlx5_core_dev *dev = devlink_priv(devlink);
445 
446 	if (!MLX5_ESWITCH_MANAGER(dev))
447 		return -EOPNOTSUPP;
448 
449 	if (ctx->val.vbool)
450 		return mlx5_lag_mpesw_enable(dev);
451 
452 	mlx5_lag_mpesw_disable(dev);
453 	return 0;
454 }
455 
456 static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
457 					  struct devlink_param_gset_ctx *ctx)
458 {
459 	struct mlx5_core_dev *dev = devlink_priv(devlink);
460 
461 	if (!MLX5_ESWITCH_MANAGER(dev))
462 		return -EOPNOTSUPP;
463 
464 	ctx->val.vbool = mlx5_lag_is_mpesw(dev);
465 	return 0;
466 }
467 
468 static int mlx5_devlink_esw_multiport_validate(struct devlink *devlink, u32 id,
469 					       union devlink_param_value val,
470 					       struct netlink_ext_ack *extack)
471 {
472 	struct mlx5_core_dev *dev = devlink_priv(devlink);
473 
474 	if (!MLX5_ESWITCH_MANAGER(dev)) {
475 		NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
476 		return -EOPNOTSUPP;
477 	}
478 
479 	if (mlx5_eswitch_mode(dev) != MLX5_ESWITCH_OFFLOADS) {
480 		NL_SET_ERR_MSG_MOD(extack,
481 				   "E-Switch must be in switchdev mode");
482 		return -EBUSY;
483 	}
484 
485 	return 0;
486 }
487 
488 #endif
489 
490 static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
491 					  union devlink_param_value val,
492 					  struct netlink_ext_ack *extack)
493 {
494 	return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL;
495 }
496 
497 static const struct devlink_param mlx5_devlink_params[] = {
498 	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
499 			      NULL, NULL, mlx5_devlink_enable_roce_validate),
500 #ifdef CONFIG_MLX5_ESWITCH
501 	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
502 			     "fdb_large_groups", DEVLINK_PARAM_TYPE_U32,
503 			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
504 			     NULL, NULL,
505 			     mlx5_devlink_large_group_num_validate),
506 	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
507 			     "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
508 			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
509 			     mlx5_devlink_esw_multiport_get,
510 			     mlx5_devlink_esw_multiport_set,
511 			     mlx5_devlink_esw_multiport_validate),
512 #endif
513 	DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
514 			      NULL, NULL, mlx5_devlink_eq_depth_validate),
515 	DEVLINK_PARAM_GENERIC(EVENT_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
516 			      NULL, NULL, mlx5_devlink_eq_depth_validate),
517 };
518 
519 static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
520 {
521 	struct mlx5_core_dev *dev = devlink_priv(devlink);
522 	union devlink_param_value value;
523 
524 	value.vbool = MLX5_CAP_GEN(dev, roce);
525 	devl_param_driverinit_value_set(devlink,
526 					DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
527 					value);
528 
529 #ifdef CONFIG_MLX5_ESWITCH
530 	value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
531 	devl_param_driverinit_value_set(devlink,
532 					MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
533 					value);
534 #endif
535 
536 	value.vu32 = MLX5_COMP_EQ_SIZE;
537 	devl_param_driverinit_value_set(devlink,
538 					DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
539 					value);
540 
541 	value.vu32 = MLX5_NUM_ASYNC_EQE;
542 	devl_param_driverinit_value_set(devlink,
543 					DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
544 					value);
545 }
546 
547 static const struct devlink_param mlx5_devlink_eth_params[] = {
548 	DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
549 			      NULL, NULL, NULL),
550 };
551 
552 static int mlx5_devlink_eth_params_register(struct devlink *devlink)
553 {
554 	struct mlx5_core_dev *dev = devlink_priv(devlink);
555 	union devlink_param_value value;
556 	int err;
557 
558 	if (!mlx5_eth_supported(dev))
559 		return 0;
560 
561 	err = devl_params_register(devlink, mlx5_devlink_eth_params,
562 				   ARRAY_SIZE(mlx5_devlink_eth_params));
563 	if (err)
564 		return err;
565 
566 	value.vbool = true;
567 	devl_param_driverinit_value_set(devlink,
568 					DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
569 					value);
570 	return 0;
571 }
572 
573 static void mlx5_devlink_eth_params_unregister(struct devlink *devlink)
574 {
575 	struct mlx5_core_dev *dev = devlink_priv(devlink);
576 
577 	if (!mlx5_eth_supported(dev))
578 		return;
579 
580 	devl_params_unregister(devlink, mlx5_devlink_eth_params,
581 			       ARRAY_SIZE(mlx5_devlink_eth_params));
582 }
583 
584 static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
585 					     union devlink_param_value val,
586 					     struct netlink_ext_ack *extack)
587 {
588 	struct mlx5_core_dev *dev = devlink_priv(devlink);
589 	bool new_state = val.vbool;
590 
591 	if (new_state && !mlx5_rdma_supported(dev))
592 		return -EOPNOTSUPP;
593 	return 0;
594 }
595 
596 static const struct devlink_param mlx5_devlink_rdma_params[] = {
597 	DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
598 			      NULL, NULL, mlx5_devlink_enable_rdma_validate),
599 };
600 
601 static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
602 {
603 	union devlink_param_value value;
604 	int err;
605 
606 	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
607 		return 0;
608 
609 	err = devl_params_register(devlink, mlx5_devlink_rdma_params,
610 				   ARRAY_SIZE(mlx5_devlink_rdma_params));
611 	if (err)
612 		return err;
613 
614 	value.vbool = true;
615 	devl_param_driverinit_value_set(devlink,
616 					DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
617 					value);
618 	return 0;
619 }
620 
621 static void mlx5_devlink_rdma_params_unregister(struct devlink *devlink)
622 {
623 	if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
624 		return;
625 
626 	devl_params_unregister(devlink, mlx5_devlink_rdma_params,
627 			       ARRAY_SIZE(mlx5_devlink_rdma_params));
628 }
629 
630 static const struct devlink_param mlx5_devlink_vnet_params[] = {
631 	DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
632 			      NULL, NULL, NULL),
633 };
634 
635 static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
636 {
637 	struct mlx5_core_dev *dev = devlink_priv(devlink);
638 	union devlink_param_value value;
639 	int err;
640 
641 	if (!mlx5_vnet_supported(dev))
642 		return 0;
643 
644 	err = devl_params_register(devlink, mlx5_devlink_vnet_params,
645 				   ARRAY_SIZE(mlx5_devlink_vnet_params));
646 	if (err)
647 		return err;
648 
649 	value.vbool = true;
650 	devl_param_driverinit_value_set(devlink,
651 					DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
652 					value);
653 	return 0;
654 }
655 
656 static void mlx5_devlink_vnet_params_unregister(struct devlink *devlink)
657 {
658 	struct mlx5_core_dev *dev = devlink_priv(devlink);
659 
660 	if (!mlx5_vnet_supported(dev))
661 		return;
662 
663 	devl_params_unregister(devlink, mlx5_devlink_vnet_params,
664 			       ARRAY_SIZE(mlx5_devlink_vnet_params));
665 }
666 
667 static int mlx5_devlink_auxdev_params_register(struct devlink *devlink)
668 {
669 	int err;
670 
671 	err = mlx5_devlink_eth_params_register(devlink);
672 	if (err)
673 		return err;
674 
675 	err = mlx5_devlink_rdma_params_register(devlink);
676 	if (err)
677 		goto rdma_err;
678 
679 	err = mlx5_devlink_vnet_params_register(devlink);
680 	if (err)
681 		goto vnet_err;
682 	return 0;
683 
684 vnet_err:
685 	mlx5_devlink_rdma_params_unregister(devlink);
686 rdma_err:
687 	mlx5_devlink_eth_params_unregister(devlink);
688 	return err;
689 }
690 
691 static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink)
692 {
693 	mlx5_devlink_vnet_params_unregister(devlink);
694 	mlx5_devlink_rdma_params_unregister(devlink);
695 	mlx5_devlink_eth_params_unregister(devlink);
696 }
697 
698 static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id,
699 					     union devlink_param_value val,
700 					     struct netlink_ext_ack *extack)
701 {
702 	struct mlx5_core_dev *dev = devlink_priv(devlink);
703 
704 	if (val.vu32 == 0) {
705 		NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0");
706 		return -EINVAL;
707 	}
708 
709 	if (!is_power_of_2(val.vu32)) {
710 		NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs");
711 		return -EINVAL;
712 	}
713 
714 	if (ilog2(val.vu32) >
715 	    MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
716 		NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range");
717 		return -EINVAL;
718 	}
719 
720 	return 0;
721 }
722 
723 static const struct devlink_param mlx5_devlink_max_uc_list_params[] = {
724 	DEVLINK_PARAM_GENERIC(MAX_MACS, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
725 			      NULL, NULL, mlx5_devlink_max_uc_list_validate),
726 };
727 
728 static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink)
729 {
730 	struct mlx5_core_dev *dev = devlink_priv(devlink);
731 	union devlink_param_value value;
732 	int err;
733 
734 	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
735 		return 0;
736 
737 	err = devl_params_register(devlink, mlx5_devlink_max_uc_list_params,
738 				   ARRAY_SIZE(mlx5_devlink_max_uc_list_params));
739 	if (err)
740 		return err;
741 
742 	value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list);
743 	devl_param_driverinit_value_set(devlink,
744 					DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
745 					value);
746 	return 0;
747 }
748 
749 static void
750 mlx5_devlink_max_uc_list_params_unregister(struct devlink *devlink)
751 {
752 	struct mlx5_core_dev *dev = devlink_priv(devlink);
753 
754 	if (!MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list_wr_supported))
755 		return;
756 
757 	devl_params_unregister(devlink, mlx5_devlink_max_uc_list_params,
758 			       ARRAY_SIZE(mlx5_devlink_max_uc_list_params));
759 }
760 
761 #define MLX5_TRAP_DROP(_id, _group_id)					\
762 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				\
763 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
764 			     DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT)
765 
766 static const struct devlink_trap mlx5_traps_arr[] = {
767 	MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
768 	MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS),
769 };
770 
771 static const struct devlink_trap_group mlx5_trap_groups_arr[] = {
772 	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
773 };
774 
775 int mlx5_devlink_traps_register(struct devlink *devlink)
776 {
777 	struct mlx5_core_dev *core_dev = devlink_priv(devlink);
778 	int err;
779 
780 	err = devl_trap_groups_register(devlink, mlx5_trap_groups_arr,
781 					ARRAY_SIZE(mlx5_trap_groups_arr));
782 	if (err)
783 		return err;
784 
785 	err = devl_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
786 				  &core_dev->priv);
787 	if (err)
788 		goto err_trap_group;
789 	return 0;
790 
791 err_trap_group:
792 	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
793 				    ARRAY_SIZE(mlx5_trap_groups_arr));
794 	return err;
795 }
796 
797 void mlx5_devlink_traps_unregister(struct devlink *devlink)
798 {
799 	devl_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
800 	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
801 				    ARRAY_SIZE(mlx5_trap_groups_arr));
802 }
803 
804 int mlx5_devlink_params_register(struct devlink *devlink)
805 {
806 	int err;
807 
808 	err = devl_params_register(devlink, mlx5_devlink_params,
809 				   ARRAY_SIZE(mlx5_devlink_params));
810 	if (err)
811 		return err;
812 
813 	mlx5_devlink_set_params_init_values(devlink);
814 
815 	err = mlx5_devlink_auxdev_params_register(devlink);
816 	if (err)
817 		goto auxdev_reg_err;
818 
819 	err = mlx5_devlink_max_uc_list_params_register(devlink);
820 	if (err)
821 		goto max_uc_list_err;
822 
823 	return 0;
824 
825 max_uc_list_err:
826 	mlx5_devlink_auxdev_params_unregister(devlink);
827 auxdev_reg_err:
828 	devl_params_unregister(devlink, mlx5_devlink_params,
829 			       ARRAY_SIZE(mlx5_devlink_params));
830 	return err;
831 }
832 
833 void mlx5_devlink_params_unregister(struct devlink *devlink)
834 {
835 	mlx5_devlink_max_uc_list_params_unregister(devlink);
836 	mlx5_devlink_auxdev_params_unregister(devlink);
837 	devl_params_unregister(devlink, mlx5_devlink_params,
838 			       ARRAY_SIZE(mlx5_devlink_params));
839 }
840