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