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
mlx5_devlink_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)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
mlx5_fw_ver_major(u32 version)24 static u8 mlx5_fw_ver_major(u32 version)
25 {
26 return (version >> 24) & 0xff;
27 }
28
mlx5_fw_ver_minor(u32 version)29 static u8 mlx5_fw_ver_minor(u32 version)
30 {
31 return (version >> 16) & 0xff;
32 }
33
mlx5_fw_ver_subminor(u32 version)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
mlx5_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)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
mlx5_devlink_reload_fw_activate(struct devlink * devlink,struct netlink_ext_ack * extack)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
mlx5_devlink_trigger_fw_live_patch(struct devlink * devlink,struct netlink_ext_ack * extack)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
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)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
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)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
mlx5_find_trap_by_id(struct mlx5_core_dev * dev,int trap_id)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
mlx5_devlink_trap_init(struct devlink * devlink,const struct devlink_trap * trap,void * trap_ctx)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
mlx5_devlink_trap_fini(struct devlink * devlink,const struct devlink_trap * trap,void * trap_ctx)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
mlx5_devlink_trap_action_set(struct devlink * devlink,const struct devlink_trap * trap,enum devlink_trap_action action,struct netlink_ext_ack * extack)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
mlx5_devlink_trap_report(struct mlx5_core_dev * dev,int trap_id,struct sk_buff * skb,struct devlink_port * dl_port)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
mlx5_devlink_trap_get_num_active(struct mlx5_core_dev * dev)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
mlx5_devlink_traps_get_action(struct mlx5_core_dev * dev,int trap_id,enum devlink_trap_action * action)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
mlx5_devlink_alloc(struct device * dev)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
mlx5_devlink_free(struct devlink * devlink)400 void mlx5_devlink_free(struct devlink *devlink)
401 {
402 devlink_free(devlink);
403 }
404
mlx5_devlink_enable_roce_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_large_group_num_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_esw_multiport_set(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx)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
mlx5_devlink_esw_multiport_get(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx)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
mlx5_devlink_esw_multiport_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_eq_depth_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_set_params_init_values(struct devlink * devlink)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
mlx5_devlink_eth_params_register(struct devlink * devlink)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
mlx5_devlink_eth_params_unregister(struct devlink * devlink)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
mlx5_devlink_enable_rdma_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_rdma_params_register(struct devlink * devlink)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
mlx5_devlink_rdma_params_unregister(struct devlink * devlink)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
mlx5_devlink_vnet_params_register(struct devlink * devlink)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
mlx5_devlink_vnet_params_unregister(struct devlink * devlink)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
mlx5_devlink_auxdev_params_register(struct devlink * devlink)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
mlx5_devlink_auxdev_params_unregister(struct devlink * devlink)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
mlx5_devlink_max_uc_list_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)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
mlx5_devlink_max_uc_list_params_register(struct devlink * devlink)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
mlx5_devlink_max_uc_list_params_unregister(struct devlink * devlink)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
mlx5_devlink_traps_register(struct devlink * devlink)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
mlx5_devlink_traps_unregister(struct devlink * devlink)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
mlx5_devlink_params_register(struct devlink * devlink)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
mlx5_devlink_params_unregister(struct devlink * devlink)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