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