History

Merge tag 'mlx5-updates-2022-05-09' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says: ==================== mlx5-updates-2022-05-09 1) Gavin Li, adds exit route from waiting for FW init on device boot and increases FW init timeout on health recovery flow 2) Support 4 ports HCAs LAG mode Mark Bloch Says: ================ This series adds to mlx5 drivers support for 4 ports HCAs. Starting with ConnectX-7 HCAs with 4 ports are possible. As most driver parts aren't affected by such configuration most driver code is unchanged. Specially the only affected areas are: - Lag - Devcom - Merged E-Switch - Single FDB E-Switch Lag was chosen to be converted first. Creating hardware LAG when all 4 ports are added to the same bond device. Devom, merge E-Switch and single FDB E-Switch, are marked as supporting only 2 ports HCAs and future patches will add support for 4 ports HCAs. In order to activate the hardware lag a user can execute the: ip link add bond0 type bond ip link set bond0 type bond miimon 100 mode 2 ip link set eth2 master bond0 ip link set eth3 master bond0 ip link set eth4 master bond0 ip link set eth5 master bond0 Where eth2, eth3, eth4 and eth5 are the PFs of the same HCA. ================ ====================

David S. Miller committed 4 years ago

Commit dc3a2002 parents 53a332f 7f46a0b22 files · +720 −302Browse files

Unified · Split

22 files
  1. drivers/infiniband/hw/mlx5/gsi.c +1 −1
  2. drivers/infiniband/hw/mlx5/main.c +1 −0
  3. drivers/infiniband/hw/mlx5/mlx5_ib.h +1 −0
  4. drivers/infiniband/hw/mlx5/qp.c +1 −1
  5. drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 −1
  6. drivers/net/ethernet/mellanox/mlx5/core/dev.c +41 −8
  7. drivers/net/ethernet/mellanox/mlx5/core/devlink.c +2 −2
  8. drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +0 −25
  9. drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +0 −8
  10. drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +1 −1
  11. drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c +173 −0
  12. drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +361 −176
  13. drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +15 −1
  14. drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c +77 −52
  15. drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.h +8 −7
  16. drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +9 −7
  17. drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h +2 −0
  18. drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c +1 −0
  19. drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h +1 −0
  20. drivers/net/ethernet/mellanox/mlx5/core/main.c +18 −10
  21. drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +2 −1
  22. include/linux/mlx5/driver.h +4 −1
drivers/infiniband/hw/mlx5/gsi.c+1−1
@@ -100,7 +100,7 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp, · 99 unmodified lines
100100 port_type) == MLX5_CAP_PORT_TYPE_IB)
101101 num_qps = pd->device->attrs.max_pkeys;
102102 else if (dev->lag_active)
103− num_qps = MLX5_MAX_PORTS;
103+ num_qps = dev->lag_ports;
104104 }
105105
106106 gsi = &mqp->gsi;
drivers/infiniband/hw/mlx5/main.c+1−0
@@ -2991,6 +2991,7 @@ static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev) · 2990 unmodified lines
29912991 }
29922992
29932993 dev->flow_db->lag_demux_ft = ft;
2994+ dev->lag_ports = mlx5_lag_get_num_ports(mdev);
29942995 dev->lag_active = true;
29952996 return 0;
29962997
drivers/infiniband/hw/mlx5/mlx5_ib.h+1−0
@@ -1131,6 +1131,7 @@ struct mlx5_ib_dev { · 1130 unmodified lines
11311131 struct xarray sig_mrs;
11321132 struct mlx5_port_caps port_caps[MLX5_MAX_PORTS];
11331133 u16 pkey_table_len;
1134+ u8 lag_ports;
11341135 };
11351136
11361137 static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
drivers/infiniband/hw/mlx5/qp.c+1−1
@@ -3907,7 +3907,7 @@ static unsigned int get_tx_affinity_rr(struct mlx5_ib_dev *dev, · 3906 unmodified lines
39073907 tx_port_affinity = &dev->port[port_num].roce.tx_port_affinity;
39083908
39093909 return (unsigned int)atomic_add_return(1, tx_port_affinity) %
3910− MLX5_MAX_PORTS + 1;
3910+ (dev->lag_active ? dev->lag_ports : MLX5_CAP_GEN(dev->mdev, num_lag_ports)) + 1;
39113911 }
39123912
39133913 static bool qp_supports_affinity(struct mlx5_ib_qp *qp)
drivers/net/ethernet/mellanox/mlx5/core/Makefile+1−1
@@ -14,7 +14,7 @@ obj-$(CONFIG_MLX5_CORE) += mlx5_core.o · 13 unmodified lines
1414 mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
1515 health.o mcg.o cq.o alloc.o port.o mr.o pd.o \
1616 transobj.o vport.o sriov.o fs_cmd.o fs_core.o pci_irq.o \
17− fs_counters.o fs_ft_pool.o rl.o lag/lag.o dev.o events.o wq.o lib/gid.o \
17+ fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \
1818 lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \
1919 diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o \
2020 fw_reset.o qos.o lib/tout.o
drivers/net/ethernet/mellanox/mlx5/core/dev.c+41−8
@@ -555,12 +555,9 @@ static u32 mlx5_gen_pci_id(const struct mlx5_core_dev *dev) · 554 unmodified lines
555555 PCI_SLOT(dev->pdev->devfn));
556556 }
557557
558−static int next_phys_dev(struct device *dev, const void *data)
558+static int _next_phys_dev(struct mlx5_core_dev *mdev,
559+ const struct mlx5_core_dev *curr)
559560 {
560− struct mlx5_adev *madev = container_of(dev, struct mlx5_adev, adev.dev);
561− struct mlx5_core_dev *mdev = madev->mdev;
562− const struct mlx5_core_dev *curr = data;
563−
564561 if (!mlx5_core_is_pf(mdev))
565562 return 0;
566563
@@ -574,8 +571,30 @@ static int next_phys_dev(struct device *dev, const void *data) · 7 unmodified lines
574571 return 1;
575572 }
576573
577−/* Must be called with intf_mutex held */
578−struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev)
574+static int next_phys_dev(struct device *dev, const void *data)
575+{
576+ struct mlx5_adev *madev = container_of(dev, struct mlx5_adev, adev.dev);
577+ struct mlx5_core_dev *mdev = madev->mdev;
578+
579+ return _next_phys_dev(mdev, data);
580+}
581+
582+static int next_phys_dev_lag(struct device *dev, const void *data)
583+{
584+ struct mlx5_adev *madev = container_of(dev, struct mlx5_adev, adev.dev);
585+ struct mlx5_core_dev *mdev = madev->mdev;
586+
587+ if (!MLX5_CAP_GEN(mdev, vport_group_manager) ||
588+ !MLX5_CAP_GEN(mdev, lag_master) ||
589+ (MLX5_CAP_GEN(mdev, num_lag_ports) > MLX5_MAX_PORTS ||
590+ MLX5_CAP_GEN(mdev, num_lag_ports) <= 1))
591+ return 0;
592+
593+ return _next_phys_dev(mdev, data);
594+}
595+
596+static struct mlx5_core_dev *mlx5_get_next_dev(struct mlx5_core_dev *dev,
597+ int (*match)(struct device *dev, const void *data))
579598 {
580599 struct auxiliary_device *adev;
581600 struct mlx5_adev *madev;
@@ -583,7 +602,7 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev) · 1 unmodified line
583602 if (!mlx5_core_is_pf(dev))
584603 return NULL;
585604
586− adev = auxiliary_find_device(NULL, dev, &next_phys_dev);
605+ adev = auxiliary_find_device(NULL, dev, match);
587606 if (!adev)
588607 return NULL;
589608
@@ -592,6 +611,20 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev) · 2 unmodified lines
592611 return madev->mdev;
593612 }
594613
614+/* Must be called with intf_mutex held */
615+struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev)
616+{
617+ lockdep_assert_held(&mlx5_intf_mutex);
618+ return mlx5_get_next_dev(dev, &next_phys_dev);
619+}
620+
621+/* Must be called with intf_mutex held */
622+struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev)
623+{
624+ lockdep_assert_held(&mlx5_intf_mutex);
625+ return mlx5_get_next_dev(dev, &next_phys_dev_lag);
626+}
627+
595628 void mlx5_dev_list_lock(void)
596629 {
597630 mutex_lock(&mlx5_intf_mutex);
drivers/net/ethernet/mellanox/mlx5/core/devlink.c+2−2
@@ -178,13 +178,13 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a · 177 unmodified lines
178178 *actions_performed = BIT(action);
179179 switch (action) {
180180 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
181− return mlx5_load_one(dev);
181+ return mlx5_load_one(dev, false);
182182 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
183183 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
184184 break;
185185 /* On fw_activate action, also driver is reloaded and reinit performed */
186186 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
187− return mlx5_load_one(dev);
187+ return mlx5_load_one(dev, false);
188188 default:
189189 /* Unsupported action should not get to this function */
190190 WARN_ON(1);
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c+0−25
@@ -1569,9 +1569,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) · 1568 unmodified lines
15691569 ida_init(&esw->offloads.vport_metadata_ida);
15701570 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
15711571 mutex_init(&esw->state_lock);
1572− lockdep_register_key(&esw->mode_lock_key);
15731572 init_rwsem(&esw->mode_lock);
1574− lockdep_set_class(&esw->mode_lock, &esw->mode_lock_key);
15751573 refcount_set(&esw->qos.refcnt, 0);
15761574
15771575 esw->enabled_vports = 0;
@@ -1615,7 +1613,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) · 37 unmodified lines
16151613 esw->dev->priv.eswitch = NULL;
16161614 destroy_workqueue(esw->work_queue);
16171615 WARN_ON(refcount_read(&esw->qos.refcnt));
1618− lockdep_unregister_key(&esw->mode_lock_key);
16191616 mutex_destroy(&esw->state_lock);
16201617 WARN_ON(!xa_empty(&esw->offloads.vhca_map));
16211618 xa_destroy(&esw->offloads.vhca_map);
@@ -1893,17 +1890,6 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) · 271 unmodified lines
18931890 }
18941891 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
18951892
1896−bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
1897−{
1898− if ((dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
1899− dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE) ||
1900− (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
1901− dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS))
1902− return true;
1903−
1904− return false;
1905−}
1906−
19071893 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
19081894 struct mlx5_core_dev *dev1)
19091895 {
@@ -2014,17 +2000,6 @@ void mlx5_esw_unlock(struct mlx5_eswitch *esw) · 104 unmodified lines
20142000 up_write(&esw->mode_lock);
20152001 }
20162002
2017−/**
2018− * mlx5_esw_lock() - Take write lock on esw mode lock
2019− * @esw: eswitch device.
2020− */
2021−void mlx5_esw_lock(struct mlx5_eswitch *esw)
2022−{
2023− if (!mlx5_esw_allowed(esw))
2024− return;
2025− down_write(&esw->mode_lock);
2026−}
2027−
20282003 /**
20292004 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
20302005 *
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h+0−8
@@ -331,7 +331,6 @@ struct mlx5_eswitch { · 330 unmodified lines
331331 u32 large_group_num;
332332 } params;
333333 struct blocking_notifier_head n_head;
334− struct lock_class_key mode_lock_key;
335334 };
336335
337336 void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -518,8 +517,6 @@ static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev · 180 unmodified lines
518517 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan_2);
519518 }
520519
521−bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0,
522− struct mlx5_core_dev *dev1);
523520 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
524521 struct mlx5_core_dev *dev1);
525522
@@ -706,7 +703,6 @@ void mlx5_esw_get(struct mlx5_core_dev *dev); · 180 unmodified lines
706703 void mlx5_esw_put(struct mlx5_core_dev *dev);
707704 int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
708705 void mlx5_esw_unlock(struct mlx5_eswitch *esw);
709−void mlx5_esw_lock(struct mlx5_eswitch *esw);
710706
711707 void esw_vport_change_handle_locked(struct mlx5_vport *vport);
712708
@@ -724,7 +720,6 @@ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } · 11 unmodified lines
724720 static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}
725721 static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }
726722 static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf) {}
727−static inline bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1) { return true; }
728723 static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
729724 static inline
730725 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }
@@ -733,9 +728,6 @@ static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) · 2 unmodified lines
733728 return ERR_PTR(-EOPNOTSUPP);
734729 }
735730
736−static inline void mlx5_esw_unlock(struct mlx5_eswitch *esw) { return; }
737−static inline void mlx5_esw_lock(struct mlx5_eswitch *esw) { return; }
738−
739731 static inline struct mlx5_flow_handle *
740732 esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
741733 {
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c+1−1
@@ -148,7 +148,7 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) · 147 unmodified lines
148148 if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
149149 complete(&fw_reset->done);
150150 } else {
151− mlx5_load_one(dev);
151+ mlx5_load_one(dev, false);
152152 devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0,
153153 BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
154154 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));
drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c+173−0
@@ -0,0 +1,173 @@
1+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3+
4+#include "lag.h"
5+
6+static char *get_str_mode_type(struct mlx5_lag *ldev)
7+{
8+ if (ldev->flags & MLX5_LAG_FLAG_ROCE)
9+ return "roce";
10+ if (ldev->flags & MLX5_LAG_FLAG_SRIOV)
11+ return "switchdev";
12+ if (ldev->flags & MLX5_LAG_FLAG_MULTIPATH)
13+ return "multipath";
14+
15+ return NULL;
16+}
17+
18+static int type_show(struct seq_file *file, void *priv)
19+{
20+ struct mlx5_core_dev *dev = file->private;
21+ struct mlx5_lag *ldev;
22+ char *mode = NULL;
23+
24+ ldev = dev->priv.lag;
25+ mutex_lock(&ldev->lock);
26+ if (__mlx5_lag_is_active(ldev))
27+ mode = get_str_mode_type(ldev);
28+ mutex_unlock(&ldev->lock);
29+ if (!mode)
30+ return -EINVAL;
31+ seq_printf(file, "%s\n", mode);
32+
33+ return 0;
34+}
35+
36+static int port_sel_mode_show(struct seq_file *file, void *priv)
37+{
38+ struct mlx5_core_dev *dev = file->private;
39+ struct mlx5_lag *ldev;
40+ int ret = 0;
41+ char *mode;
42+
43+ ldev = dev->priv.lag;
44+ mutex_lock(&ldev->lock);
45+ if (__mlx5_lag_is_active(ldev))
46+ mode = get_str_port_sel_mode(ldev->flags);
47+ else
48+ ret = -EINVAL;
49+ mutex_unlock(&ldev->lock);
50+ if (ret || !mode)
51+ return ret;
52+
53+ seq_printf(file, "%s\n", mode);
54+ return 0;
55+}
56+
57+static int state_show(struct seq_file *file, void *priv)
58+{
59+ struct mlx5_core_dev *dev = file->private;
60+ struct mlx5_lag *ldev;
61+ bool active;
62+
63+ ldev = dev->priv.lag;
64+ mutex_lock(&ldev->lock);
65+ active = __mlx5_lag_is_active(ldev);
66+ mutex_unlock(&ldev->lock);
67+ seq_printf(file, "%s\n", active ? "active" : "disabled");
68+ return 0;
69+}
70+
71+static int flags_show(struct seq_file *file, void *priv)
72+{
73+ struct mlx5_core_dev *dev = file->private;
74+ struct mlx5_lag *ldev;
75+ bool shared_fdb;
76+ bool lag_active;
77+
78+ ldev = dev->priv.lag;
79+ mutex_lock(&ldev->lock);
80+ lag_active = __mlx5_lag_is_active(ldev);
81+ if (lag_active)
82+ shared_fdb = ldev->shared_fdb;
83+
84+ mutex_unlock(&ldev->lock);
85+ if (!lag_active)
86+ return -EINVAL;
87+
88+ seq_printf(file, "%s:%s\n", "shared_fdb", shared_fdb ? "on" : "off");
89+ return 0;
90+}
91+
92+static int mapping_show(struct seq_file *file, void *priv)
93+{
94+ struct mlx5_core_dev *dev = file->private;
95+ u8 ports[MLX5_MAX_PORTS] = {};
96+ struct mlx5_lag *ldev;
97+ bool hash = false;
98+ bool lag_active;
99+ int num_ports;
100+ int i;
101+
102+ ldev = dev->priv.lag;
103+ mutex_lock(&ldev->lock);
104+ lag_active = __mlx5_lag_is_active(ldev);
105+ if (lag_active) {
106+ if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED) {
107+ mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, ports,
108+ &num_ports);
109+ hash = true;
110+ } else {
111+ for (i = 0; i < ldev->ports; i++)
112+ ports[i] = ldev->v2p_map[i];
113+ num_ports = ldev->ports;
114+ }
115+ }
116+ mutex_unlock(&ldev->lock);
117+ if (!lag_active)
118+ return -EINVAL;
119+
120+ for (i = 0; i < num_ports; i++) {
121+ if (hash)
122+ seq_printf(file, "%d\n", ports[i] + 1);
123+ else
124+ seq_printf(file, "%d:%d\n", i + 1, ports[i]);
125+ }
126+
127+ return 0;
128+}
129+
130+static int members_show(struct seq_file *file, void *priv)
131+{
132+ struct mlx5_core_dev *dev = file->private;
133+ struct mlx5_lag *ldev;
134+ int i;
135+
136+ ldev = dev->priv.lag;
137+ mutex_lock(&ldev->lock);
138+ for (i = 0; i < ldev->ports; i++) {
139+ if (!ldev->pf[i].dev)
140+ continue;
141+ seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device));
142+ }
143+ mutex_unlock(&ldev->lock);
144+
145+ return 0;
146+}
147+
148+DEFINE_SHOW_ATTRIBUTE(type);
149+DEFINE_SHOW_ATTRIBUTE(port_sel_mode);
150+DEFINE_SHOW_ATTRIBUTE(state);
151+DEFINE_SHOW_ATTRIBUTE(flags);
152+DEFINE_SHOW_ATTRIBUTE(mapping);
153+DEFINE_SHOW_ATTRIBUTE(members);
154+
155+void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev)
156+{
157+ struct dentry *dbg;
158+
159+ dbg = debugfs_create_dir("lag", mlx5_debugfs_get_dev_root(dev));
160+ dev->priv.dbg.lag_debugfs = dbg;
161+
162+ debugfs_create_file("type", 0444, dbg, dev, &type_fops);
163+ debugfs_create_file("port_sel_mode", 0444, dbg, dev, &port_sel_mode_fops);
164+ debugfs_create_file("state", 0444, dbg, dev, &state_fops);
165+ debugfs_create_file("flags", 0444, dbg, dev, &flags_fops);
166+ debugfs_create_file("mapping", 0444, dbg, dev, &mapping_fops);
167+ debugfs_create_file("members", 0444, dbg, dev, &members_fops);
168+}
169+
170+void mlx5_ldev_remove_debugfs(struct dentry *dbg)
171+{
172+ debugfs_remove_recursive(dbg);
173+}
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c+361−176
@@ -53,8 +53,7 @@ enum { · 52 unmodified lines
5353 */
5454 static DEFINE_SPINLOCK(lag_lock);
5555
56−static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1,
57− u8 remap_port2, bool shared_fdb, u8 flags)
56+static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, bool shared_fdb, u8 flags)
5857 {
5958 u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
6059 void *lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
@@ -63,8 +62,8 @@ static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1, · 2 unmodified lines
6362
6463 MLX5_SET(lagc, lag_ctx, fdb_selection_mode, shared_fdb);
6564 if (!(flags & MLX5_LAG_FLAG_HASH_BASED)) {
66− MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
67− MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
65+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
66+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
6867 } else {
6968 MLX5_SET(lagc, lag_ctx, port_select_mode,
7069 MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT);
@@ -73,8 +72,8 @@ static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1, · 2 unmodified lines
7372 return mlx5_cmd_exec_in(dev, create_lag, in);
7473 }
7574
76−static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 remap_port1,
77− u8 remap_port2)
75+static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 num_ports,
76+ u8 *ports)
7877 {
7978 u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
8079 void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
@@ -82,8 +81,8 @@ static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 remap_port1, · 1 unmodified line
8281 MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
8382 MLX5_SET(modify_lag_in, in, field_select, 0x1);
8483
85− MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
86− MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
84+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
85+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
8786
8887 return mlx5_cmd_exec_in(dev, modify_lag, in);
8988 }
@@ -108,6 +107,75 @@ int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev) · 18 unmodified lines
108107 }
109108 EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
110109
110+static void mlx5_infer_tx_disabled(struct lag_tracker *tracker, u8 num_ports,
111+ u8 *ports, int *num_disabled)
112+{
113+ int i;
114+
115+ *num_disabled = 0;
116+ for (i = 0; i < num_ports; i++) {
117+ if (!tracker->netdev_state[i].tx_enabled ||
118+ !tracker->netdev_state[i].link_up)
119+ ports[(*num_disabled)++] = i;
120+ }
121+}
122+
123+void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
124+ u8 *ports, int *num_enabled)
125+{
126+ int i;
127+
128+ *num_enabled = 0;
129+ for (i = 0; i < num_ports; i++) {
130+ if (tracker->netdev_state[i].tx_enabled &&
131+ tracker->netdev_state[i].link_up)
132+ ports[(*num_enabled)++] = i;
133+ }
134+
135+ if (*num_enabled == 0)
136+ mlx5_infer_tx_disabled(tracker, num_ports, ports, num_enabled);
137+}
138+
139+static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
140+ struct mlx5_lag *ldev,
141+ struct lag_tracker *tracker,
142+ u8 flags)
143+{
144+ char buf[MLX5_MAX_PORTS * 10 + 1] = {};
145+ u8 enabled_ports[MLX5_MAX_PORTS] = {};
146+ int written = 0;
147+ int num_enabled;
148+ int idx;
149+ int err;
150+ int i;
151+ int j;
152+
153+ if (flags & MLX5_LAG_FLAG_HASH_BASED) {
154+ mlx5_infer_tx_enabled(tracker, ldev->ports, enabled_ports,
155+ &num_enabled);
156+ for (i = 0; i < num_enabled; i++) {
157+ err = scnprintf(buf + written, 4, "%d, ", enabled_ports[i] + 1);
158+ if (err != 3)
159+ return;
160+ written += err;
161+ }
162+ buf[written - 2] = 0;
163+ mlx5_core_info(dev, "lag map active ports: %s\n", buf);
164+ } else {
165+ for (i = 0; i < ldev->ports; i++) {
166+ for (j = 0; j < ldev->buckets; j++) {
167+ idx = i * ldev->buckets + j;
168+ err = scnprintf(buf + written, 10,
169+ " port %d:%d", i + 1, ldev->v2p_map[idx]);
170+ if (err != 9)
171+ return;
172+ written += err;
173+ }
174+ }
175+ mlx5_core_info(dev, "lag map:%s\n", buf);
176+ }
177+}
178+
111179 static int mlx5_lag_netdev_event(struct notifier_block *this,
112180 unsigned long event, void *ptr);
113181 static void mlx5_do_bond_work(struct work_struct *work);
@@ -121,6 +189,7 @@ static void mlx5_ldev_free(struct kref *ref) · 7 unmodified lines
121189 mlx5_lag_mp_cleanup(ldev);
122190 cancel_delayed_work_sync(&ldev->bond_work);
123191 destroy_workqueue(ldev->wq);
192+ mutex_destroy(&ldev->lock);
124193 kfree(ldev);
125194 }
126195
@@ -150,6 +219,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev) · 23 unmodified lines
150219 }
151220
152221 kref_init(&ldev->ref);
222+ mutex_init(&ldev->lock);
153223 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
154224
155225 ldev->nb.notifier_call = mlx5_lag_netdev_event;
@@ -162,6 +232,8 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev) · 6 unmodified lines
162232 if (err)
163233 mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
164234 err);
235+ ldev->ports = MLX5_CAP_GEN(dev, num_lag_ports);
236+ ldev->buckets = 1;
165237
166238 return ldev;
167239 }
@@ -171,7 +243,7 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, · 3 unmodified lines
171243 {
172244 int i;
173245
174− for (i = 0; i < MLX5_MAX_PORTS; i++)
246+ for (i = 0; i < ldev->ports; i++)
175247 if (ldev->pf[i].netdev == ndev)
176248 return i;
177249
@@ -188,39 +260,72 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev) · 10 unmodified lines
188260 return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);
189261 }
190262
263+/* Create a mapping between steering slots and active ports.
264+ * As we have ldev->buckets slots per port first assume the native
265+ * mapping should be used.
266+ * If there are ports that are disabled fill the relevant slots
267+ * with mapping that points to active ports.
268+ */
191269 static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
192− u8 *port1, u8 *port2)
270+ u8 num_ports,
271+ u8 buckets,
272+ u8 *ports)
193273 {
194− bool p1en;
195− bool p2en;
274+ int disabled[MLX5_MAX_PORTS] = {};
275+ int enabled[MLX5_MAX_PORTS] = {};
276+ int disabled_ports_num = 0;
277+ int enabled_ports_num = 0;
278+ int idx;
279+ u32 rand;
280+ int i;
281+ int j;
196282
197− p1en = tracker->netdev_state[MLX5_LAG_P1].tx_enabled &&
198− tracker->netdev_state[MLX5_LAG_P1].link_up;
283+ for (i = 0; i < num_ports; i++) {
284+ if (tracker->netdev_state[i].tx_enabled &&
285+ tracker->netdev_state[i].link_up)
286+ enabled[enabled_ports_num++] = i;
287+ else
288+ disabled[disabled_ports_num++] = i;
289+ }
199290
200− p2en = tracker->netdev_state[MLX5_LAG_P2].tx_enabled &&
201− tracker->netdev_state[MLX5_LAG_P2].link_up;
291+ /* Use native mapping by default where each port's buckets
292+ * point the native port: 1 1 1 .. 1 2 2 2 ... 2 3 3 3 ... 3 etc
293+ */
294+ for (i = 0; i < num_ports; i++)
295+ for (j = 0; j < buckets; j++) {
296+ idx = i * buckets + j;
297+ ports[idx] = MLX5_LAG_EGRESS_PORT_1 + i;
298+ }
202299
203− *port1 = MLX5_LAG_EGRESS_PORT_1;
204− *port2 = MLX5_LAG_EGRESS_PORT_2;
205− if ((!p1en && !p2en) || (p1en && p2en))
300+ /* If all ports are disabled/enabled keep native mapping */
301+ if (enabled_ports_num == num_ports ||
302+ disabled_ports_num == num_ports)
206303 return;
207304
208− if (p1en)
209− *port2 = MLX5_LAG_EGRESS_PORT_1;
210− else
211− *port1 = MLX5_LAG_EGRESS_PORT_2;
305+ /* Go over the disabled ports and for each assign a random active port */
306+ for (i = 0; i < disabled_ports_num; i++) {
307+ for (j = 0; j < buckets; j++) {
308+ get_random_bytes(&rand, 4);
309+ ports[disabled[i] * buckets + j] = enabled[rand % enabled_ports_num] + 1;
310+ }
311+ }
212312 }
213313
214314 static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev)
215315 {
216− return ldev->pf[MLX5_LAG_P1].has_drop || ldev->pf[MLX5_LAG_P2].has_drop;
316+ int i;
317+
318+ for (i = 0; i < ldev->ports; i++)
319+ if (ldev->pf[i].has_drop)
320+ return true;
321+ return false;
217322 }
218323
219324 static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev)
220325 {
221326 int i;
222327
223− for (i = 0; i < MLX5_MAX_PORTS; i++) {
328+ for (i = 0; i < ldev->ports; i++) {
224329 if (!ldev->pf[i].has_drop)
225330 continue;
226331
@@ -233,12 +338,12 @@ static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev) · 6 unmodified lines
233338 static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev,
234339 struct lag_tracker *tracker)
235340 {
236− struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
237− struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
238− struct mlx5_core_dev *inactive;
239− u8 v2p_port1, v2p_port2;
240− int inactive_idx;
341+ u8 disabled_ports[MLX5_MAX_PORTS] = {};
342+ struct mlx5_core_dev *dev;
343+ int disabled_index;
344+ int num_disabled;
241345 int err;
346+ int i;
242347
243348 /* First delete the current drop rule so there won't be any dropped
244349 * packets
@@ -248,58 +353,60 @@ static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev, · 3 unmodified lines
248353 if (!ldev->tracker.has_inactive)
249354 return;
250355
251− mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1, &v2p_port2);
356+ mlx5_infer_tx_disabled(tracker, ldev->ports, disabled_ports, &num_disabled);
252357
253− if (v2p_port1 == MLX5_LAG_EGRESS_PORT_1) {
254− inactive = dev1;
255− inactive_idx = MLX5_LAG_P2;
256− } else {
257− inactive = dev0;
258− inactive_idx = MLX5_LAG_P1;
358+ for (i = 0; i < num_disabled; i++) {
359+ disabled_index = disabled_ports[i];
360+ dev = ldev->pf[disabled_index].dev;
361+ err = mlx5_esw_acl_ingress_vport_drop_rule_create(dev->priv.eswitch,
362+ MLX5_VPORT_UPLINK);
363+ if (!err)
364+ ldev->pf[disabled_index].has_drop = true;
365+ else
366+ mlx5_core_err(dev,
367+ "Failed to create lag drop rule, error: %d", err);
259368 }
260−
261− err = mlx5_esw_acl_ingress_vport_drop_rule_create(inactive->priv.eswitch,
262− MLX5_VPORT_UPLINK);
263− if (!err)
264− ldev->pf[inactive_idx].has_drop = true;
265− else
266− mlx5_core_err(inactive,
267− "Failed to create lag drop rule, error: %d", err);
268369 }
269370
270−static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 v2p_port1, u8 v2p_port2)
371+static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
271372 {
272373 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
273374
274375 if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED)
275− return mlx5_lag_port_sel_modify(ldev, v2p_port1, v2p_port2);
276− return mlx5_cmd_modify_lag(dev0, v2p_port1, v2p_port2);
376+ return mlx5_lag_port_sel_modify(ldev, ports);
377+ return mlx5_cmd_modify_lag(dev0, ldev->ports, ports);
277378 }
278379
279380 void mlx5_modify_lag(struct mlx5_lag *ldev,
280381 struct lag_tracker *tracker)
281382 {
383+ u8 ports[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS] = {};
282384 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
283− u8 v2p_port1, v2p_port2;
385+ int idx;
284386 int err;
387+ int i;
388+ int j;
285389
286− mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1,
287− &v2p_port2);
390+ mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ports);
288391
289− if (v2p_port1 != ldev->v2p_map[MLX5_LAG_P1] ||
290− v2p_port2 != ldev->v2p_map[MLX5_LAG_P2]) {
291− err = _mlx5_modify_lag(ldev, v2p_port1, v2p_port2);
292− if (err) {
293− mlx5_core_err(dev0,
294− "Failed to modify LAG (%d)\n",
295− err);
296− return;
392+ for (i = 0; i < ldev->ports; i++) {
393+ for (j = 0; j < ldev->buckets; j++) {
394+ idx = i * ldev->buckets + j;
395+ if (ports[idx] == ldev->v2p_map[idx])
396+ continue;
397+ err = _mlx5_modify_lag(ldev, ports);
398+ if (err) {
399+ mlx5_core_err(dev0,
400+ "Failed to modify LAG (%d)\n",
401+ err);
402+ return;
403+ }
404+ memcpy(ldev->v2p_map, ports, sizeof(ports));
405+
406+ mlx5_lag_print_mapping(dev0, ldev, tracker,
407+ ldev->flags);
408+ break;
297409 }
298− ldev->v2p_map[MLX5_LAG_P1] = v2p_port1;
299− ldev->v2p_map[MLX5_LAG_P2] = v2p_port2;
300− mlx5_core_info(dev0, "modify lag map port 1:%d port 2:%d",
301− ldev->v2p_map[MLX5_LAG_P1],
302− ldev->v2p_map[MLX5_LAG_P2]);
303410 }
304411
305412 if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
@@ -307,20 +414,47 @@ void mlx5_modify_lag(struct mlx5_lag *ldev, · 1 unmodified line
307414 mlx5_lag_drop_rule_setup(ldev, tracker);
308415 }
309416
310−static void mlx5_lag_set_port_sel_mode(struct mlx5_lag *ldev,
311− struct lag_tracker *tracker, u8 *flags)
417+#define MLX5_LAG_ROCE_HASH_PORTS_SUPPORTED 4
418+static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
419+ struct lag_tracker *tracker, u8 *flags)
312420 {
313− bool roce_lag = !!(*flags & MLX5_LAG_FLAG_ROCE);
314421 struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
315422
316− if (roce_lag ||
317− !MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) ||
318− tracker->tx_type != NETDEV_LAG_TX_TYPE_HASH)
319− return;
320− *flags |= MLX5_LAG_FLAG_HASH_BASED;
423+ if (ldev->ports == MLX5_LAG_ROCE_HASH_PORTS_SUPPORTED) {
424+ /* Four ports are support only in hash mode */
425+ if (!MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table))
426+ return -EINVAL;
427+ *flags |= MLX5_LAG_FLAG_HASH_BASED;
428+ if (ldev->ports > 2)
429+ ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
430+ }
431+
432+ return 0;
433+}
434+
435+static int mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
436+ struct lag_tracker *tracker, u8 *flags)
437+{
438+ struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
439+
440+ if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
441+ tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH)
442+ *flags |= MLX5_LAG_FLAG_HASH_BASED;
443+
444+ return 0;
445+}
446+
447+static int mlx5_lag_set_port_sel_mode(struct mlx5_lag *ldev,
448+ struct lag_tracker *tracker, u8 *flags)
449+{
450+ bool roce_lag = !!(*flags & MLX5_LAG_FLAG_ROCE);
451+
452+ if (roce_lag)
453+ return mlx5_lag_set_port_sel_mode_roce(ldev, tracker, flags);
454+ return mlx5_lag_set_port_sel_mode_offloads(ldev, tracker, flags);
321455 }
322456
323−static char *get_str_port_sel_mode(u8 flags)
457+char *get_str_port_sel_mode(u8 flags)
324458 {
325459 if (flags & MLX5_LAG_FLAG_HASH_BASED)
326460 return "hash";
@@ -336,12 +470,11 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, · 9 unmodified lines
336470 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
337471 int err;
338472
339− mlx5_core_info(dev0, "lag map port 1:%d port 2:%d shared_fdb:%d mode:%s",
340− ldev->v2p_map[MLX5_LAG_P1], ldev->v2p_map[MLX5_LAG_P2],
473+ mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
474+ mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
341475 shared_fdb, get_str_port_sel_mode(flags));
342476
343− err = mlx5_cmd_create_lag(dev0, ldev->v2p_map[MLX5_LAG_P1],
344− ldev->v2p_map[MLX5_LAG_P2], shared_fdb, flags);
477+ err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, shared_fdb, flags);
345478 if (err) {
346479 mlx5_core_err(dev0,
347480 "Failed to create LAG (%d)\n",
@@ -377,13 +510,15 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, · 29 unmodified lines
377510 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
378511 int err;
379512
380− mlx5_infer_tx_affinity_mapping(tracker, &ldev->v2p_map[MLX5_LAG_P1],
381− &ldev->v2p_map[MLX5_LAG_P2]);
382− mlx5_lag_set_port_sel_mode(ldev, tracker, &flags);
513+ err = mlx5_lag_set_port_sel_mode(ldev, tracker, &flags);
514+ if (err)
515+ return err;
516+
517+ mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
518+
383519 if (flags & MLX5_LAG_FLAG_HASH_BASED) {
384520 err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,
385− ldev->v2p_map[MLX5_LAG_P1],
386− ldev->v2p_map[MLX5_LAG_P2]);
521+ ldev->v2p_map);
387522 if (err) {
388523 mlx5_core_err(dev0,
389524 "Failed to create LAG port selection(%d)\n",
@@ -455,25 +590,43 @@ static int mlx5_deactivate_lag(struct mlx5_lag *ldev) · 65 unmodified lines
455590 return 0;
456591 }
457592
593+#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2
458594 static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
459595 {
460− if (!ldev->pf[MLX5_LAG_P1].dev || !ldev->pf[MLX5_LAG_P2].dev)
461− return false;
596+#ifdef CONFIG_MLX5_ESWITCH
597+ u8 mode;
598+#endif
599+ int i;
600+
601+ for (i = 0; i < ldev->ports; i++)
602+ if (!ldev->pf[i].dev)
603+ return false;
462604
463605 #ifdef CONFIG_MLX5_ESWITCH
464− return mlx5_esw_lag_prereq(ldev->pf[MLX5_LAG_P1].dev,
465− ldev->pf[MLX5_LAG_P2].dev);
606+ mode = mlx5_eswitch_mode(ldev->pf[MLX5_LAG_P1].dev);
607+
608+ if (mode != MLX5_ESWITCH_NONE && mode != MLX5_ESWITCH_OFFLOADS)
609+ return false;
610+
611+ for (i = 0; i < ldev->ports; i++)
612+ if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
613+ return false;
614+
615+ if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
616+ return false;
466617 #else
467− return (!mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P1].dev) &&
468− !mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P2].dev));
618+ for (i = 0; i < ldev->ports; i++)
619+ if (mlx5_sriov_is_enabled(ldev->pf[i].dev))
620+ return false;
469621 #endif
622+ return true;
470623 }
471624
472625 static void mlx5_lag_add_devices(struct mlx5_lag *ldev)
473626 {
474627 int i;
475628
476− for (i = 0; i < MLX5_MAX_PORTS; i++) {
629+ for (i = 0; i < ldev->ports; i++) {
477630 if (!ldev->pf[i].dev)
478631 continue;
479632
@@ -490,7 +643,7 @@ static void mlx5_lag_remove_devices(struct mlx5_lag *ldev) · 10 unmodified lines
490643 {
491644 int i;
492645
493− for (i = 0; i < MLX5_MAX_PORTS; i++) {
646+ for (i = 0; i < ldev->ports; i++) {
494647 if (!ldev->pf[i].dev)
495648 continue;
496649
@@ -510,6 +663,7 @@ static void mlx5_disable_lag(struct mlx5_lag *ldev) · 13 unmodified lines
510663 bool shared_fdb = ldev->shared_fdb;
511664 bool roce_lag;
512665 int err;
666+ int i;
513667
514668 roce_lag = __mlx5_lag_is_roce(ldev);
515669
@@ -520,7 +674,8 @@ static void mlx5_disable_lag(struct mlx5_lag *ldev) · 4 unmodified lines
520674 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
521675 mlx5_rescan_drivers_locked(dev0);
522676 }
523− mlx5_nic_vport_disable_roce(dev1);
677+ for (i = 1; i < ldev->ports; i++)
678+ mlx5_nic_vport_disable_roce(ldev->pf[i].dev);
524679 }
525680
526681 err = mlx5_deactivate_lag(ldev);
@@ -557,6 +712,23 @@ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) · 30 unmodified lines
557712 return false;
558713 }
559714
715+static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev)
716+{
717+ bool roce_lag = true;
718+ int i;
719+
720+ for (i = 0; i < ldev->ports; i++)
721+ roce_lag = roce_lag && !mlx5_sriov_is_enabled(ldev->pf[i].dev);
722+
723+#ifdef CONFIG_MLX5_ESWITCH
724+ for (i = 0; i < ldev->ports; i++)
725+ roce_lag = roce_lag &&
726+ ldev->pf[i].dev->priv.eswitch->mode == MLX5_ESWITCH_NONE;
727+#endif
728+
729+ return roce_lag;
730+}
731+
560732 static void mlx5_do_bond(struct mlx5_lag *ldev)
561733 {
562734 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
@@ -564,6 +736,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) · 1 unmodified line
564736 struct lag_tracker tracker;
565737 bool do_bond, roce_lag;
566738 int err;
739+ int i;
567740
568741 if (!mlx5_lag_is_ready(ldev)) {
569742 do_bond = false;
@@ -580,14 +753,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) · 10 unmodified lines
580753 if (do_bond && !__mlx5_lag_is_active(ldev)) {
581754 bool shared_fdb = mlx5_shared_fdb_supported(ldev);
582755
583− roce_lag = !mlx5_sriov_is_enabled(dev0) &&
584− !mlx5_sriov_is_enabled(dev1);
585−
586−#ifdef CONFIG_MLX5_ESWITCH
587− roce_lag = roce_lag &&
588− dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
589− dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE;
590−#endif
756+ roce_lag = mlx5_lag_is_roce_lag(ldev);
591757
592758 if (shared_fdb || roce_lag)
593759 mlx5_lag_remove_devices(ldev);
@@ -604,7 +770,8 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) · 10 unmodified lines
604770 } else if (roce_lag) {
605771 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
606772 mlx5_rescan_drivers_locked(dev0);
607− mlx5_nic_vport_enable_roce(dev1);
773+ for (i = 1; i < ldev->ports; i++)
774+ mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
608775 } else if (shared_fdb) {
609776 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
610777 mlx5_rescan_drivers_locked(dev0);
@@ -636,31 +803,11 @@ static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay) · 25 unmodified lines
636803 queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
637804 }
638805
639−static void mlx5_lag_lock_eswitches(struct mlx5_core_dev *dev0,
640− struct mlx5_core_dev *dev1)
641−{
642− if (dev0)
643− mlx5_esw_lock(dev0->priv.eswitch);
644− if (dev1)
645− mlx5_esw_lock(dev1->priv.eswitch);
646−}
647−
648−static void mlx5_lag_unlock_eswitches(struct mlx5_core_dev *dev0,
649− struct mlx5_core_dev *dev1)
650−{
651− if (dev1)
652− mlx5_esw_unlock(dev1->priv.eswitch);
653− if (dev0)
654− mlx5_esw_unlock(dev0->priv.eswitch);
655−}
656−
657806 static void mlx5_do_bond_work(struct work_struct *work)
658807 {
659808 struct delayed_work *delayed_work = to_delayed_work(work);
660809 struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
661810 bond_work);
662− struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
663− struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
664811 int status;
665812
666813 status = mlx5_dev_list_trylock();
@@ -669,15 +816,16 @@ static void mlx5_do_bond_work(struct work_struct *work) · 2 unmodified lines
669816 return;
670817 }
671818
819+ mutex_lock(&ldev->lock);
672820 if (ldev->mode_changes_in_progress) {
821+ mutex_unlock(&ldev->lock);
673822 mlx5_dev_list_unlock();
674823 mlx5_queue_bond_work(ldev, HZ);
675824 return;
676825 }
677826
678− mlx5_lag_lock_eswitches(dev0, dev1);
679827 mlx5_do_bond(ldev);
680− mlx5_lag_unlock_eswitches(dev0, dev1);
828+ mutex_unlock(&ldev->lock);
681829 mlx5_dev_list_unlock();
682830 }
683831
@@ -691,7 +839,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 7 unmodified lines
691839 bool is_bonded, is_in_lag, mode_supported;
692840 bool has_inactive = 0;
693841 struct slave *slave;
694− int bond_status = 0;
842+ u8 bond_status = 0;
695843 int num_slaves = 0;
696844 int changed = 0;
697845 int idx;
@@ -722,7 +870,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 24 unmodified lines
722870 rcu_read_unlock();
723871
724872 /* None of this lagdev's netdevs are slaves of this master. */
725− if (!(bond_status & 0x3))
873+ if (!(bond_status & GENMASK(ldev->ports - 1, 0)))
726874 return 0;
727875
728876 if (lag_upper_info) {
@@ -735,7 +883,8 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 6 unmodified lines
735883 * A device is considered bonded if both its physical ports are slaves
736884 * of the same lag master, and only them.
737885 */
738− is_in_lag = num_slaves == MLX5_MAX_PORTS && bond_status == 0x3;
886+ is_in_lag = num_slaves == ldev->ports &&
887+ bond_status == GENMASK(ldev->ports - 1, 0);
739888
740889 /* Lag mode must be activebackup or hash. */
741890 mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP ||
@@ -864,7 +1013,7 @@ static void mlx5_ldev_add_netdev(struct mlx5_lag *ldev, · 122 unmodified lines
8641013 {
8651014 unsigned int fn = mlx5_get_dev_index(dev);
8661015
867− if (fn >= MLX5_MAX_PORTS)
1016+ if (fn >= ldev->ports)
8681017 return;
8691018
8701019 spin_lock(&lag_lock);
@@ -880,7 +1029,7 @@ static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev, · 9 unmodified lines
8801029 int i;
8811030
8821031 spin_lock(&lag_lock);
883− for (i = 0; i < MLX5_MAX_PORTS; i++) {
1032+ for (i = 0; i < ldev->ports; i++) {
8841033 if (ldev->pf[i].netdev == netdev) {
8851034 ldev->pf[i].netdev = NULL;
8861035 break;
@@ -894,24 +1043,23 @@ static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev, · 7 unmodified lines
8941043 {
8951044 unsigned int fn = mlx5_get_dev_index(dev);
8961045
897− if (fn >= MLX5_MAX_PORTS)
1046+ if (fn >= ldev->ports)
8981047 return;
8991048
9001049 ldev->pf[fn].dev = dev;
9011050 dev->priv.lag = ldev;
9021051 }
9031052
904−/* Must be called with intf_mutex held */
9051053 static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,
9061054 struct mlx5_core_dev *dev)
9071055 {
9081056 int i;
9091057
910− for (i = 0; i < MLX5_MAX_PORTS; i++)
1058+ for (i = 0; i < ldev->ports; i++)
9111059 if (ldev->pf[i].dev == dev)
9121060 break;
9131061
914− if (i == MLX5_MAX_PORTS)
1062+ if (i == ldev->ports)
9151063 return;
9161064
9171065 ldev->pf[i].dev = NULL;
@@ -924,12 +1072,7 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) · 6 unmodified lines
9241072 struct mlx5_lag *ldev = NULL;
9251073 struct mlx5_core_dev *tmp_dev;
9261074
927− if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
928− !MLX5_CAP_GEN(dev, lag_master) ||
929− MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_MAX_PORTS)
930− return 0;
931−
932− tmp_dev = mlx5_get_next_phys_dev(dev);
1075+ tmp_dev = mlx5_get_next_phys_dev_lag(dev);
9331076 if (tmp_dev)
9341077 ldev = tmp_dev->priv.lag;
9351078
@@ -939,13 +1082,18 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) · 3 unmodified lines
9391082 mlx5_core_err(dev, "Failed to alloc lag dev\n");
9401083 return 0;
9411084 }
942− } else {
943− if (ldev->mode_changes_in_progress)
944− return -EAGAIN;
945− mlx5_ldev_get(ldev);
1085+ mlx5_ldev_add_mdev(ldev, dev);
1086+ return 0;
9461087 }
9471088
1089+ mutex_lock(&ldev->lock);
1090+ if (ldev->mode_changes_in_progress) {
1091+ mutex_unlock(&ldev->lock);
1092+ return -EAGAIN;
1093+ }
1094+ mlx5_ldev_get(ldev);
9481095 mlx5_ldev_add_mdev(ldev, dev);
1096+ mutex_unlock(&ldev->lock);
9491097
9501098 return 0;
9511099 }
@@ -958,15 +1106,19 @@ void mlx5_lag_remove_mdev(struct mlx5_core_dev *dev) · 6 unmodified lines
9581106 if (!ldev)
9591107 return;
9601108
1109+ /* mdev is being removed, might as well remove debugfs
1110+ * as early as possible.
1111+ */
1112+ mlx5_ldev_remove_debugfs(dev->priv.dbg.lag_debugfs);
9611113 recheck:
962− mlx5_dev_list_lock();
1114+ mutex_lock(&ldev->lock);
9631115 if (ldev->mode_changes_in_progress) {
964− mlx5_dev_list_unlock();
1116+ mutex_unlock(&ldev->lock);
9651117 msleep(100);
9661118 goto recheck;
9671119 }
9681120 mlx5_ldev_remove_mdev(ldev, dev);
969− mlx5_dev_list_unlock();
1121+ mutex_unlock(&ldev->lock);
9701122 mlx5_ldev_put(ldev);
9711123 }
9721124
@@ -974,35 +1126,45 @@ void mlx5_lag_add_mdev(struct mlx5_core_dev *dev) · 1 unmodified line
9741126 {
9751127 int err;
9761128
1129+ if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
1130+ !MLX5_CAP_GEN(dev, lag_master) ||
1131+ (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS ||
1132+ MLX5_CAP_GEN(dev, num_lag_ports) <= 1))
1133+ return;
1134+
9771135 recheck:
9781136 mlx5_dev_list_lock();
9791137 err = __mlx5_lag_dev_add_mdev(dev);
1138+ mlx5_dev_list_unlock();
1139+
9801140 if (err) {
981− mlx5_dev_list_unlock();
9821141 msleep(100);
9831142 goto recheck;
9841143 }
985− mlx5_dev_list_unlock();
1144+ mlx5_ldev_add_debugfs(dev);
9861145 }
9871146
988−/* Must be called with intf_mutex held */
9891147 void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,
9901148 struct net_device *netdev)
9911149 {
9921150 struct mlx5_lag *ldev;
1151+ bool lag_is_active;
9931152
9941153 ldev = mlx5_lag_dev(dev);
9951154 if (!ldev)
9961155 return;
9971156
1157+ mutex_lock(&ldev->lock);
9981158 mlx5_ldev_remove_netdev(ldev, netdev);
9991159 ldev->flags &= ~MLX5_LAG_FLAG_READY;
10001160
1001− if (__mlx5_lag_is_active(ldev))
1161+ lag_is_active = __mlx5_lag_is_active(ldev);
1162+ mutex_unlock(&ldev->lock);
1163+
1164+ if (lag_is_active)
10021165 mlx5_queue_bond_work(ldev, 0);
10031166 }
10041167
1005−/* Must be called with intf_mutex held */
10061168 void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
10071169 struct net_device *netdev)
10081170 {
@@ -1013,14 +1175,16 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev, · 4 unmodified lines
10131175 if (!ldev)
10141176 return;
10151177
1178+ mutex_lock(&ldev->lock);
10161179 mlx5_ldev_add_netdev(ldev, dev, netdev);
10171180
1018− for (i = 0; i < MLX5_MAX_PORTS; i++)
1181+ for (i = 0; i < ldev->ports; i++)
10191182 if (!ldev->pf[i].dev)
10201183 break;
10211184
1022− if (i >= MLX5_MAX_PORTS)
1185+ if (i >= ldev->ports)
10231186 ldev->flags |= MLX5_LAG_FLAG_READY;
1187+ mutex_unlock(&ldev->lock);
10241188 mlx5_queue_bond_work(ldev, 0);
10251189 }
10261190
@@ -1097,8 +1261,6 @@ EXPORT_SYMBOL(mlx5_lag_is_shared_fdb); · 70 unmodified lines
10971261
10981262 void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
10991263 {
1100− struct mlx5_core_dev *dev0;
1101− struct mlx5_core_dev *dev1;
11021264 struct mlx5_lag *ldev;
11031265
11041266 ldev = mlx5_lag_dev(dev);
@@ -1106,16 +1268,13 @@ void mlx5_lag_disable_change(struct mlx5_core_dev *dev) · 1 unmodified line
11061268 return;
11071269
11081270 mlx5_dev_list_lock();
1109−
1110− dev0 = ldev->pf[MLX5_LAG_P1].dev;
1111− dev1 = ldev->pf[MLX5_LAG_P2].dev;
1271+ mutex_lock(&ldev->lock);
11121272
11131273 ldev->mode_changes_in_progress++;
1114− if (__mlx5_lag_is_active(ldev)) {
1115− mlx5_lag_lock_eswitches(dev0, dev1);
1274+ if (__mlx5_lag_is_active(ldev))
11161275 mlx5_disable_lag(ldev);
1117− mlx5_lag_unlock_eswitches(dev0, dev1);
1118− }
1276+
1277+ mutex_unlock(&ldev->lock);
11191278 mlx5_dev_list_unlock();
11201279 }
11211280
@@ -1127,9 +1286,9 @@ void mlx5_lag_enable_change(struct mlx5_core_dev *dev) · 5 unmodified lines
11271286 if (!ldev)
11281287 return;
11291288
1130− mlx5_dev_list_lock();
1289+ mutex_lock(&ldev->lock);
11311290 ldev->mode_changes_in_progress--;
1132− mlx5_dev_list_unlock();
1291+ mutex_unlock(&ldev->lock);
11331292 mlx5_queue_bond_work(ldev, 0);
11341293 }
11351294
@@ -1137,6 +1296,7 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev) · 1 unmodified line
11371296 {
11381297 struct net_device *ndev = NULL;
11391298 struct mlx5_lag *ldev;
1299+ int i;
11401300
11411301 spin_lock(&lag_lock);
11421302 ldev = mlx5_lag_dev(dev);
@@ -1145,9 +1305,11 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev) · 2 unmodified lines
11451305 goto unlock;
11461306
11471307 if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
1148− ndev = ldev->tracker.netdev_state[MLX5_LAG_P1].tx_enabled ?
1149− ldev->pf[MLX5_LAG_P1].netdev :
1150− ldev->pf[MLX5_LAG_P2].netdev;
1308+ for (i = 0; i < ldev->ports; i++)
1309+ if (ldev->tracker.netdev_state[i].tx_enabled)
1310+ ndev = ldev->pf[i].netdev;
1311+ if (!ndev)
1312+ ndev = ldev->pf[ldev->ports - 1].netdev;
11511313 } else {
11521314 ndev = ldev->pf[MLX5_LAG_P1].netdev;
11531315 }
@@ -1166,18 +1328,21 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev, · 12 unmodified lines
11661328 {
11671329 struct mlx5_lag *ldev;
11681330 u8 port = 0;
1331+ int i;
11691332
11701333 spin_lock(&lag_lock);
11711334 ldev = mlx5_lag_dev(dev);
11721335 if (!(ldev && __mlx5_lag_is_roce(ldev)))
11731336 goto unlock;
11741337
1175− if (ldev->pf[MLX5_LAG_P1].netdev == slave)
1176− port = MLX5_LAG_P1;
1177− else
1178− port = MLX5_LAG_P2;
1338+ for (i = 0; i < ldev->ports; i++) {
1339+ if (ldev->pf[MLX5_LAG_P1].netdev == slave) {
1340+ port = i;
1341+ break;
1342+ }
1343+ }
11791344
1180− port = ldev->v2p_map[port];
1345+ port = ldev->v2p_map[port * ldev->buckets];
11811346
11821347 unlock:
11831348 spin_unlock(&lag_lock);
@@ -1185,6 +1350,18 @@ unlock: · 1 unmodified line
11851350 }
11861351 EXPORT_SYMBOL(mlx5_lag_get_slave_port);
11871352
1353+u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev)
1354+{
1355+ struct mlx5_lag *ldev;
1356+
1357+ ldev = mlx5_lag_dev(dev);
1358+ if (!ldev)
1359+ return 0;
1360+
1361+ return ldev->ports;
1362+}
1363+EXPORT_SYMBOL(mlx5_lag_get_num_ports);
1364+
11881365 struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
11891366 {
11901367 struct mlx5_core_dev *peer_dev = NULL;
@@ -1211,7 +1388,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 20 unmodified lines
12111388 size_t *offsets)
12121389 {
12131390 int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
1214− struct mlx5_core_dev *mdev[MLX5_MAX_PORTS];
1391+ struct mlx5_core_dev **mdev;
12151392 struct mlx5_lag *ldev;
12161393 int num_ports;
12171394 int ret, i, j;
@@ -1221,14 +1398,20 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 3 unmodified lines
12211398 if (!out)
12221399 return -ENOMEM;
12231400
1401+ mdev = kvzalloc(sizeof(mdev[0]) * MLX5_MAX_PORTS, GFP_KERNEL);
1402+ if (!mdev) {
1403+ ret = -ENOMEM;
1404+ goto free_out;
1405+ }
1406+
12241407 memset(values, 0, sizeof(*values) * num_counters);
12251408
12261409 spin_lock(&lag_lock);
12271410 ldev = mlx5_lag_dev(dev);
12281411 if (ldev && __mlx5_lag_is_active(ldev)) {
1229− num_ports = MLX5_MAX_PORTS;
1230− mdev[MLX5_LAG_P1] = ldev->pf[MLX5_LAG_P1].dev;
1231− mdev[MLX5_LAG_P2] = ldev->pf[MLX5_LAG_P2].dev;
1412+ num_ports = ldev->ports;
1413+ for (i = 0; i < ldev->ports; i++)
1414+ mdev[i] = ldev->pf[i].dev;
12321415 } else {
12331416 num_ports = 1;
12341417 mdev[MLX5_LAG_P1] = dev;
@@ -1243,13 +1426,15 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 8 unmodified lines
12431426 ret = mlx5_cmd_exec_inout(mdev[i], query_cong_statistics, in,
12441427 out);
12451428 if (ret)
1246− goto free;
1429+ goto free_mdev;
12471430
12481431 for (j = 0; j < num_counters; ++j)
12491432 values[j] += be64_to_cpup((__be64 *)(out + offsets[j]));
12501433 }
12511434
1252−free:
1435+free_mdev:
1436+ kvfree(mdev);
1437+free_out:
12531438 kvfree(out);
12541439 return ret;
12551440 }
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h+15−1
@@ -4,6 +4,9 @@ · 3 unmodified lines
44 #ifndef __MLX5_LAG_H__
55 #define __MLX5_LAG_H__
66
7+#include <linux/debugfs.h>
8+
9+#define MLX5_LAG_MAX_HASH_BUCKETS 16
710 #include "mlx5_core.h"
811 #include "mp.h"
912 #include "port_sel.h"
@@ -45,9 +48,11 @@ struct lag_tracker { · 35 unmodified lines
4548 */
4649 struct mlx5_lag {
4750 u8 flags;
51+ u8 ports;
52+ u8 buckets;
4853 int mode_changes_in_progress;
4954 bool shared_fdb;
50− u8 v2p_map[MLX5_MAX_PORTS];
55+ u8 v2p_map[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS];
5156 struct kref ref;
5257 struct lag_func pf[MLX5_MAX_PORTS];
5358 struct lag_tracker tracker;
@@ -56,6 +61,8 @@ struct mlx5_lag { · 2 unmodified lines
5661 struct notifier_block nb;
5762 struct lag_mp lag_mp;
5863 struct mlx5_lag_port_sel port_sel;
64+ /* Protect lag fields/state changes */
65+ struct mutex lock;
5966 };
6067
6168 static inline struct mlx5_lag *
@@ -85,4 +92,11 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, · 23 unmodified lines
8592 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
8693 struct net_device *ndev);
8794
95+char *get_str_port_sel_mode(u8 flags);
96+void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
97+ u8 *ports, int *num_enabled);
98+
99+void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev);
100+void mlx5_ldev_remove_debugfs(struct dentry *dbg);
101+
88102 #endif /* __MLX5_LAG_H__ */
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c+77−52
@@ -12,7 +12,8 @@ enum { · 11 unmodified lines
1212
1313 static struct mlx5_flow_group *
1414 mlx5_create_hash_flow_group(struct mlx5_flow_table *ft,
15− struct mlx5_flow_definer *definer)
15+ struct mlx5_flow_definer *definer,
16+ u8 rules)
1617 {
1718 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1819 struct mlx5_flow_group *fg;
@@ -25,7 +26,7 @@ mlx5_create_hash_flow_group(struct mlx5_flow_table *ft, · 6 unmodified lines
2526 MLX5_SET(create_flow_group_in, in, match_definer_id,
2627 mlx5_get_match_definer_id(definer));
2728 MLX5_SET(create_flow_group_in, in, start_flow_index, 0);
28− MLX5_SET(create_flow_group_in, in, end_flow_index, MLX5_MAX_PORTS - 1);
29+ MLX5_SET(create_flow_group_in, in, end_flow_index, rules - 1);
2930 MLX5_SET(create_flow_group_in, in, group_type,
3031 MLX5_CREATE_FLOW_GROUP_IN_GROUP_TYPE_HASH_SPLIT);
3132
@@ -36,7 +37,7 @@ mlx5_create_hash_flow_group(struct mlx5_flow_table *ft, · 4 unmodified lines
3637
3738 static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
3839 struct mlx5_lag_definer *lag_definer,
39− u8 port1, u8 port2)
40+ u8 *ports)
4041 {
4142 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
4243 struct mlx5_flow_table_attr ft_attr = {};
@@ -44,8 +45,10 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, · 1 unmodified line
4445 MLX5_DECLARE_FLOW_ACT(flow_act);
4546 struct mlx5_flow_namespace *ns;
4647 int err, i;
48+ int idx;
49+ int j;
4750
48− ft_attr.max_fte = MLX5_MAX_PORTS;
51+ ft_attr.max_fte = ldev->ports * ldev->buckets;
4952 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;
5053
5154 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_PORT_SEL);
@@ -61,7 +64,8 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, · 9 unmodified lines
6164 }
6265
6366 lag_definer->fg = mlx5_create_hash_flow_group(lag_definer->ft,
64− lag_definer->definer);
67+ lag_definer->definer,
68+ ft_attr.max_fte);
6569 if (IS_ERR(lag_definer->fg)) {
6670 err = PTR_ERR(lag_definer->fg);
6771 goto destroy_ft;
@@ -70,19 +74,25 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, · 2 unmodified lines
7074 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
7175 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
7276 flow_act.flags |= FLOW_ACT_NO_APPEND;
73− for (i = 0; i < MLX5_MAX_PORTS; i++) {
74− u8 affinity = i == 0 ? port1 : port2;
75−
76− dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev,
77− vhca_id);
78− lag_definer->rules[i] = mlx5_add_flow_rules(lag_definer->ft,
79− NULL, &flow_act,
80− &dest, 1);
81− if (IS_ERR(lag_definer->rules[i])) {
82− err = PTR_ERR(lag_definer->rules[i]);
83− while (i--)
84− mlx5_del_flow_rules(lag_definer->rules[i]);
85− goto destroy_fg;
77+ for (i = 0; i < ldev->ports; i++) {
78+ for (j = 0; j < ldev->buckets; j++) {
79+ u8 affinity;
80+
81+ idx = i * ldev->buckets + j;
82+ affinity = ports[idx];
83+
84+ dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev,
85+ vhca_id);
86+ lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft,
87+ NULL, &flow_act,
88+ &dest, 1);
89+ if (IS_ERR(lag_definer->rules[idx])) {
90+ err = PTR_ERR(lag_definer->rules[idx]);
91+ while (i--)
92+ while (j--)
93+ mlx5_del_flow_rules(lag_definer->rules[idx]);
94+ goto destroy_fg;
95+ }
8696 }
8797 }
8898
@@ -279,8 +289,7 @@ static int mlx5_lag_set_definer(u32 *match_definer_mask, · 190 unmodified lines
279289
280290 static struct mlx5_lag_definer *
281291 mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
282− enum mlx5_traffic_types tt, bool tunnel, u8 port1,
283− u8 port2)
292+ enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
284293 {
285294 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
286295 struct mlx5_lag_definer *lag_definer;
@@ -308,7 +317,7 @@ mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash, · 21 unmodified lines
308317 goto free_mask;
309318 }
310319
311− err = mlx5_lag_create_port_sel_table(ldev, lag_definer, port1, port2);
320+ err = mlx5_lag_create_port_sel_table(ldev, lag_definer, ports);
312321 if (err)
313322 goto destroy_match_definer;
314323
@@ -329,10 +338,16 @@ static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev, · 14 unmodified lines
329338 struct mlx5_lag_definer *lag_definer)
330339 {
331340 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
341+ int idx;
332342 int i;
343+ int j;
333344
334− for (i = 0; i < MLX5_MAX_PORTS; i++)
335− mlx5_del_flow_rules(lag_definer->rules[i]);
345+ for (i = 0; i < ldev->ports; i++) {
346+ for (j = 0; j < ldev->buckets; j++) {
347+ idx = i * ldev->buckets + j;
348+ mlx5_del_flow_rules(lag_definer->rules[idx]);
349+ }
350+ }
336351 mlx5_destroy_flow_group(lag_definer->fg);
337352 mlx5_destroy_flow_table(lag_definer->ft);
338353 mlx5_destroy_match_definer(dev, lag_definer->definer);
@@ -356,7 +371,7 @@ static void mlx5_lag_destroy_definers(struct mlx5_lag *ldev) · 17 unmodified lines
356371
357372 static int mlx5_lag_create_definers(struct mlx5_lag *ldev,
358373 enum netdev_lag_hash hash_type,
359− u8 port1, u8 port2)
374+ u8 *ports)
360375 {
361376 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
362377 struct mlx5_lag_definer *lag_definer;
@@ -364,7 +379,7 @@ static int mlx5_lag_create_definers(struct mlx5_lag *ldev, · 1 unmodified line
364379
365380 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
366381 lag_definer = mlx5_lag_create_definer(ldev, hash_type, tt,
367− false, port1, port2);
382+ false, ports);
368383 if (IS_ERR(lag_definer)) {
369384 err = PTR_ERR(lag_definer);
370385 goto destroy_definers;
@@ -376,7 +391,7 @@ static int mlx5_lag_create_definers(struct mlx5_lag *ldev, · 5 unmodified lines
376391
377392 lag_definer =
378393 mlx5_lag_create_definer(ldev, hash_type, tt,
379− true, port1, port2);
394+ true, ports);
380395 if (IS_ERR(lag_definer)) {
381396 err = PTR_ERR(lag_definer);
382397 goto destroy_definers;
@@ -513,13 +528,13 @@ static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev) · 130 unmodified lines
513528 }
514529
515530 int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
516− enum netdev_lag_hash hash_type, u8 port1, u8 port2)
531+ enum netdev_lag_hash hash_type, u8 *ports)
517532 {
518533 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
519534 int err;
520535
521536 set_tt_map(port_sel, hash_type);
522− err = mlx5_lag_create_definers(ldev, hash_type, port1, port2);
537+ err = mlx5_lag_create_definers(ldev, hash_type, ports);
523538 if (err)
524539 return err;
525540
@@ -543,52 +558,62 @@ destroy_definers: · 17 unmodified lines
543558 return err;
544559 }
545560
546−static int
547−mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
548− struct mlx5_lag_definer **definers,
549− u8 port1, u8 port2)
561+static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
562+ struct mlx5_lag_definer *def,
563+ u8 *ports)
550564 {
551− struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
552565 struct mlx5_flow_destination dest = {};
566+ int idx;
553567 int err;
554− int tt;
568+ int i;
569+ int j;
555570
556571 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
557572 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
558573
559− for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
560− struct mlx5_flow_handle **rules = definers[tt]->rules;
574+ for (i = 0; i < ldev->ports; i++) {
575+ for (j = 0; j < ldev->buckets; j++) {
576+ idx = i * ldev->buckets + j;
577+ if (ldev->v2p_map[i] == ports[i])
578+ continue;
561579
562− if (ldev->v2p_map[MLX5_LAG_P1] != port1) {
563− dest.vport.vhca_id =
564− MLX5_CAP_GEN(ldev->pf[port1 - 1].dev, vhca_id);
565− err = mlx5_modify_rule_destination(rules[MLX5_LAG_P1],
566− &dest, NULL);
580+ dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
581+ vhca_id);
582+ err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL);
567583 if (err)
568584 return err;
569585 }
586+ }
570587
571− if (ldev->v2p_map[MLX5_LAG_P2] != port2) {
572− dest.vport.vhca_id =
573− MLX5_CAP_GEN(ldev->pf[port2 - 1].dev, vhca_id);
574− err = mlx5_modify_rule_destination(rules[MLX5_LAG_P2],
575− &dest, NULL);
576− if (err)
577− return err;
578− }
588+ return 0;
589+}
590+
591+static int
592+mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
593+ struct mlx5_lag_definer **definers,
594+ u8 *ports)
595+{
596+ struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
597+ int err;
598+ int tt;
599+
600+ for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
601+ err = __mlx5_lag_modify_definers_destinations(ldev, definers[tt], ports);
602+ if (err)
603+ return err;
579604 }
580605
581606 return 0;
582607 }
583608
584−int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2)
609+int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
585610 {
586611 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
587612 int err;
588613
589614 err = mlx5_lag_modify_definers_destinations(ldev,
590615 port_sel->outer.definers,
591− port1, port2);
616+ ports);
592617 if (err)
593618 return err;
594619
@@ -597,7 +622,7 @@ int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2) · 2 unmodified lines
597622
598623 return mlx5_lag_modify_definers_destinations(ldev,
599624 port_sel->inner.definers,
600− port1, port2);
625+ ports);
601626 }
602627
603628 void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev)
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.h+8−7
@@ -10,7 +10,10 @@ struct mlx5_lag_definer { · 9 unmodified lines
1010 struct mlx5_flow_definer *definer;
1111 struct mlx5_flow_table *ft;
1212 struct mlx5_flow_group *fg;
13− struct mlx5_flow_handle *rules[MLX5_MAX_PORTS];
13+ /* Each port has ldev->buckets number of rules and they are arrange in
14+ * [port * buckets .. port * buckets + buckets) locations
15+ */
16+ struct mlx5_flow_handle *rules[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS];
1417 };
1518
1619 struct mlx5_lag_ttc {
@@ -27,22 +30,20 @@ struct mlx5_lag_port_sel { · 10 unmodified lines
2730
2831 #ifdef CONFIG_MLX5_ESWITCH
2932
30−int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2);
33+int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports);
3134 void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev);
3235 int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
33− enum netdev_lag_hash hash_type, u8 port1,
34− u8 port2);
36+ enum netdev_lag_hash hash_type, u8 *ports);
3537
3638 #else /* CONFIG_MLX5_ESWITCH */
3739 static inline int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
3840 enum netdev_lag_hash hash_type,
39− u8 port1, u8 port2)
41+ u8 *ports)
4042 {
4143 return 0;
4244 }
4345
44−static inline int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1,
45− u8 port2)
46+static inline int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
4647 {
4748 return 0;
4849 }
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c+9−7
@@ -14,7 +14,7 @@ static LIST_HEAD(devcom_list); · 13 unmodified lines
1414 struct mlx5_devcom_component {
1515 struct {
1616 void *data;
17− } device[MLX5_MAX_PORTS];
17+ } device[MLX5_DEVCOM_PORTS_SUPPORTED];
1818
1919 mlx5_devcom_event_handler_t handler;
2020 struct rw_semaphore sem;
@@ -25,7 +25,7 @@ struct mlx5_devcom_list { · 4 unmodified lines
2525 struct list_head list;
2626
2727 struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS];
28− struct mlx5_core_dev *devs[MLX5_MAX_PORTS];
28+ struct mlx5_core_dev *devs[MLX5_DEVCOM_PORTS_SUPPORTED];
2929 };
3030
3131 struct mlx5_devcom {
@@ -74,13 +74,15 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) · 42 unmodified lines
7474
7575 if (!mlx5_core_is_pf(dev))
7676 return NULL;
77+ if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
78+ return NULL;
7779
7880 sguid0 = mlx5_query_nic_system_image_guid(dev);
7981 list_for_each_entry(iter, &devcom_list, list) {
8082 struct mlx5_core_dev *tmp_dev = NULL;
8183
8284 idx = -1;
83− for (i = 0; i < MLX5_MAX_PORTS; i++) {
85+ for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
8486 if (iter->devs[i])
8587 tmp_dev = iter->devs[i];
8688 else
@@ -134,11 +136,11 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom) · 47 unmodified lines
134136
135137 kfree(devcom);
136138
137− for (i = 0; i < MLX5_MAX_PORTS; i++)
139+ for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
138140 if (priv->devs[i])
139141 break;
140142
141− if (i != MLX5_MAX_PORTS)
143+ if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
142144 return;
143145
144146 list_del(&priv->list);
@@ -191,7 +193,7 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom, · 46 unmodified lines
191193
192194 comp = &devcom->priv->components[id];
193195 down_write(&comp->sem);
194− for (i = 0; i < MLX5_MAX_PORTS; i++)
196+ for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
195197 if (i != devcom->idx && comp->device[i].data) {
196198 err = comp->handler(event, comp->device[i].data,
197199 event_data);
@@ -239,7 +241,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, · 41 unmodified lines
239241 return NULL;
240242 }
241243
242− for (i = 0; i < MLX5_MAX_PORTS; i++)
244+ for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
243245 if (i != devcom->idx)
244246 break;
245247
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h+2−0
@@ -6,6 +6,8 @@ · 5 unmodified lines
66
77 #include <linux/mlx5/driver.h>
88
9+#define MLX5_DEVCOM_PORTS_SUPPORTED 2
10+
911 enum mlx5_devcom_components {
1012 MLX5_DEVCOM_ESW_OFFLOADS,
1113
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c+1−0
@@ -10,6 +10,7 @@ struct mlx5_timeouts { · 9 unmodified lines
1010
1111 static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {
1212 [MLX5_TO_FW_PRE_INIT_TIMEOUT_MS] = 120000,
13+ [MLX5_TO_FW_PRE_INIT_ON_RECOVERY_TIMEOUT_MS] = 7200000,
1314 [MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS] = 20000,
1415 [MLX5_TO_FW_PRE_INIT_WAIT_MS] = 2,
1516 [MLX5_TO_FW_INIT_MS] = 2000,
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h+1−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
77 enum mlx5_timeouts_types {
88 /* pre init timeouts (not read from FW) */
99 MLX5_TO_FW_PRE_INIT_TIMEOUT_MS,
10+ MLX5_TO_FW_PRE_INIT_ON_RECOVERY_TIMEOUT_MS,
1011 MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS,
1112 MLX5_TO_FW_PRE_INIT_WAIT_MS,
1213
drivers/net/ethernet/mellanox/mlx5/core/main.c+18−10
@@ -189,7 +189,8 @@ static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili, · 188 unmodified lines
189189 fw_initializing = ioread32be(&dev->iseg->initializing);
190190 if (!(fw_initializing >> 31))
191191 break;
192− if (time_after(jiffies, end)) {
192+ if (time_after(jiffies, end) ||
193+ test_and_clear_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state)) {
193194 err = -EBUSY;
194195 break;
195196 }
@@ -1002,7 +1003,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) · 806 unmodified lines
10021003 mlx5_devcom_unregister_device(dev->priv.devcom);
10031004 }
10041005
1005−static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot)
1006+static int mlx5_function_setup(struct mlx5_core_dev *dev, u64 timeout)
10061007 {
10071008 int err;
10081009
@@ -1017,11 +1018,11 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) · 8 unmodified lines
10171018
10181019 /* wait for firmware to accept initialization segments configurations
10191020 */
1020− err = wait_fw_init(dev, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT),
1021+ err = wait_fw_init(dev, timeout,
10211022 mlx5_tout_ms(dev, FW_PRE_INIT_WARN_MESSAGE_INTERVAL));
10221023 if (err) {
10231024 mlx5_core_err(dev, "Firmware over %llu MS in pre-initializing state, aborting\n",
1024− mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
1025+ timeout);
10251026 return err;
10261027 }
10271028
@@ -1271,7 +1272,7 @@ int mlx5_init_one(struct mlx5_core_dev *dev) · 243 unmodified lines
12711272 mutex_lock(&dev->intf_state_mutex);
12721273 dev->state = MLX5_DEVICE_STATE_UP;
12731274
1274− err = mlx5_function_setup(dev, true);
1275+ err = mlx5_function_setup(dev, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
12751276 if (err)
12761277 goto err_function;
12771278
@@ -1335,9 +1336,10 @@ out: · 57 unmodified lines
13351336 mutex_unlock(&dev->intf_state_mutex);
13361337 }
13371338
1338−int mlx5_load_one(struct mlx5_core_dev *dev)
1339+int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery)
13391340 {
13401341 int err = 0;
1342+ u64 timeout;
13411343
13421344 mutex_lock(&dev->intf_state_mutex);
13431345 if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
@@ -1347,7 +1349,11 @@ int mlx5_load_one(struct mlx5_core_dev *dev) · 3 unmodified lines
13471349 /* remove any previous indication of internal error */
13481350 dev->state = MLX5_DEVICE_STATE_UP;
13491351
1350− err = mlx5_function_setup(dev, false);
1352+ if (recovery)
1353+ timeout = mlx5_tout_ms(dev, FW_PRE_INIT_ON_RECOVERY_TIMEOUT);
1354+ else
1355+ timeout = mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT);
1356+ err = mlx5_function_setup(dev, timeout);
13511357 if (err)
13521358 goto err_function;
13531359
@@ -1602,6 +1608,7 @@ static void remove_one(struct pci_dev *pdev) · 248 unmodified lines
16021608 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
16031609 struct devlink *devlink = priv_to_devlink(dev);
16041610
1611+ set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
16051612 devlink_unregister(devlink);
16061613 mlx5_sriov_disable(pdev);
16071614 mlx5_crdump_disable(dev);
@@ -1717,7 +1724,7 @@ static void mlx5_pci_resume(struct pci_dev *pdev) · 109 unmodified lines
17171724
17181725 mlx5_pci_trace(dev, "Enter, loading driver..\n");
17191726
1720− err = mlx5_load_one(dev);
1727+ err = mlx5_load_one(dev, false);
17211728
17221729 mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err,
17231730 !err ? "recovered" : "Failed");
@@ -1785,6 +1792,7 @@ static void shutdown(struct pci_dev *pdev) · 61 unmodified lines
17851792 int err;
17861793
17871794 mlx5_core_info(dev, "Shutdown was called\n");
1795+ set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
17881796 err = mlx5_try_fast_unload(dev);
17891797 if (err)
17901798 mlx5_unload_one(dev);
@@ -1804,7 +1812,7 @@ static int mlx5_resume(struct pci_dev *pdev) · 13 unmodified lines
18041812 {
18051813 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
18061814
1807− return mlx5_load_one(dev);
1815+ return mlx5_load_one(dev, false);
18081816 }
18091817
18101818 static const struct pci_device_id mlx5_core_pci_table[] = {
@@ -1849,7 +1857,7 @@ int mlx5_recover_device(struct mlx5_core_dev *dev) · 38 unmodified lines
18491857 return -EIO;
18501858 }
18511859
1852− return mlx5_load_one(dev);
1860+ return mlx5_load_one(dev, true);
18531861 }
18541862
18551863 static struct pci_driver mlx5_core_driver = {
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h+2−1
@@ -210,6 +210,7 @@ void mlx5_detach_device(struct mlx5_core_dev *dev); · 209 unmodified lines
210210 int mlx5_register_device(struct mlx5_core_dev *dev);
211211 void mlx5_unregister_device(struct mlx5_core_dev *dev);
212212 struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
213+struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev);
213214 void mlx5_dev_list_lock(void);
214215 void mlx5_dev_list_unlock(void);
215216 int mlx5_dev_list_trylock(void);
@@ -290,7 +291,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev); · 74 unmodified lines
290291 int mlx5_init_one(struct mlx5_core_dev *dev);
291292 void mlx5_uninit_one(struct mlx5_core_dev *dev);
292293 void mlx5_unload_one(struct mlx5_core_dev *dev);
293−int mlx5_load_one(struct mlx5_core_dev *dev);
294+int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
294295
295296 int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out);
296297
include/linux/mlx5/driver.h+4−1
@@ -84,7 +84,7 @@ enum mlx5_sqp_t { · 83 unmodified lines
8484 };
8585
8686 enum {
87− MLX5_MAX_PORTS = 2,
87+ MLX5_MAX_PORTS = 4,
8888 };
8989
9090 enum {
@@ -558,6 +558,7 @@ struct mlx5_debugfs_entries { · 467 unmodified lines
558558 struct dentry *cq_debugfs;
559559 struct dentry *cmdif_debugfs;
560560 struct dentry *pages_debugfs;
561+ struct dentry *lag_debugfs;
561562 };
562563
563564 struct mlx5_ft_pool;
@@ -632,6 +633,7 @@ enum mlx5_device_state { · 68 unmodified lines
632633
633634 enum mlx5_interface_state {
634635 MLX5_INTERFACE_STATE_UP = BIT(0),
636+ MLX5_BREAK_FW_WAIT = BIT(1),
635637 };
636638
637639 enum mlx5_pci_status {
@@ -1141,6 +1143,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 503 unmodified lines
11411143 int num_counters,
11421144 size_t *offsets);
11431145 struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev);
1146+u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev);
11441147 struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);
11451148 void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);
11461149 int mlx5_dm_sw_icm_alloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type,