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