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
100 port_type) == MLX5_CAP_PORT_TYPE_IB)100 port_type) == MLX5_CAP_PORT_TYPE_IB)
101 num_qps = pd->device->attrs.max_pkeys;101 num_qps = pd->device->attrs.max_pkeys;
102 else if (dev->lag_active)102 else if (dev->lag_active)
103 num_qps = MLX5_MAX_PORTS;103 num_qps = dev->lag_ports;
104 }104 }
105 105
106 gsi = &mqp->gsi;106 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
2991 }2991 }
2992 2992
2993 dev->flow_db->lag_demux_ft = ft;2993 dev->flow_db->lag_demux_ft = ft;
2994 dev->lag_ports = mlx5_lag_get_num_ports(mdev);
2994 dev->lag_active = true;2995 dev->lag_active = true;
2995 return 0;2996 return 0;
2996 2997
drivers/infiniband/hw/mlx5/mlx5_ib.h+1−0
@@ -1131,6 +1131,7 @@ struct mlx5_ib_dev { · 1130 unmodified lines
1131 struct xarray sig_mrs;1131 struct xarray sig_mrs;
1132 struct mlx5_port_caps port_caps[MLX5_MAX_PORTS];1132 struct mlx5_port_caps port_caps[MLX5_MAX_PORTS];
1133 u16 pkey_table_len;1133 u16 pkey_table_len;
1134 u8 lag_ports;
1134};1135};
1135 1136
1136static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)1137static 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
3907 tx_port_affinity = &dev->port[port_num].roce.tx_port_affinity;3907 tx_port_affinity = &dev->port[port_num].roce.tx_port_affinity;
3908 3908
3909 return (unsigned int)atomic_add_return(1, tx_port_affinity) %3909 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;
3911}3911}
3912 3912
3913static bool qp_supports_affinity(struct mlx5_ib_qp *qp)3913static 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
14mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \14mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
15 health.o mcg.o cq.o alloc.o port.o mr.o pd.o \15 health.o mcg.o cq.o alloc.o port.o mr.o pd.o \
16 transobj.o vport.o sriov.o fs_cmd.o fs_core.o pci_irq.o \16 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 \
18 lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \18 lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \
19 diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o \19 diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o \
20 fw_reset.o qos.o lib/tout.o20 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
555 PCI_SLOT(dev->pdev->devfn));555 PCI_SLOT(dev->pdev->devfn));
556}556}
557 557
558static int next_phys_dev(struct device *dev, const void *data)558static int _next_phys_dev(struct mlx5_core_dev *mdev,
559 const struct mlx5_core_dev *curr)
559{560{
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
564 if (!mlx5_core_is_pf(mdev))561 if (!mlx5_core_is_pf(mdev))
565 return 0;562 return 0;
566 563
@@ -574,8 +571,30 @@ static int next_phys_dev(struct device *dev, const void *data) · 7 unmodified lines
574 return 1;571 return 1;
575}572}
576 573
577/* Must be called with intf_mutex held */574static int next_phys_dev(struct device *dev, const void *data)
578struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev)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
582static 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
596static struct mlx5_core_dev *mlx5_get_next_dev(struct mlx5_core_dev *dev,
597 int (*match)(struct device *dev, const void *data))
579{598{
580 struct auxiliary_device *adev;599 struct auxiliary_device *adev;
581 struct mlx5_adev *madev;600 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
583 if (!mlx5_core_is_pf(dev))602 if (!mlx5_core_is_pf(dev))
584 return NULL;603 return NULL;
585 604
586 adev = auxiliary_find_device(NULL, dev, &next_phys_dev);605 adev = auxiliary_find_device(NULL, dev, match);
587 if (!adev)606 if (!adev)
588 return NULL;607 return NULL;
589 608
@@ -592,6 +611,20 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev) · 2 unmodified lines
592 return madev->mdev;611 return madev->mdev;
593}612}
594 613
614/* Must be called with intf_mutex held */
615struct 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 */
622struct 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
595void mlx5_dev_list_lock(void)628void mlx5_dev_list_lock(void)
596{629{
597 mutex_lock(&mlx5_intf_mutex);630 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
178 *actions_performed = BIT(action);178 *actions_performed = BIT(action);
179 switch (action) {179 switch (action) {
180 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:180 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
181 return mlx5_load_one(dev);181 return mlx5_load_one(dev, false);
182 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:182 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
183 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)183 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
184 break;184 break;
185 /* On fw_activate action, also driver is reloaded and reinit performed */185 /* On fw_activate action, also driver is reloaded and reinit performed */
186 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);186 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
187 return mlx5_load_one(dev);187 return mlx5_load_one(dev, false);
188 default:188 default:
189 /* Unsupported action should not get to this function */189 /* Unsupported action should not get to this function */
190 WARN_ON(1);190 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
1569 ida_init(&esw->offloads.vport_metadata_ida);1569 ida_init(&esw->offloads.vport_metadata_ida);
1570 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);1570 xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
1571 mutex_init(&esw->state_lock);1571 mutex_init(&esw->state_lock);
1572 lockdep_register_key(&esw->mode_lock_key);
1573 init_rwsem(&esw->mode_lock);1572 init_rwsem(&esw->mode_lock);
1574 lockdep_set_class(&esw->mode_lock, &esw->mode_lock_key);
1575 refcount_set(&esw->qos.refcnt, 0);1573 refcount_set(&esw->qos.refcnt, 0);
1576 1574
1577 esw->enabled_vports = 0;1575 esw->enabled_vports = 0;
@@ -1615,7 +1613,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) · 37 unmodified lines
1615 esw->dev->priv.eswitch = NULL;1613 esw->dev->priv.eswitch = NULL;
1616 destroy_workqueue(esw->work_queue);1614 destroy_workqueue(esw->work_queue);
1617 WARN_ON(refcount_read(&esw->qos.refcnt));1615 WARN_ON(refcount_read(&esw->qos.refcnt));
1618 lockdep_unregister_key(&esw->mode_lock_key);
1619 mutex_destroy(&esw->state_lock);1616 mutex_destroy(&esw->state_lock);
1620 WARN_ON(!xa_empty(&esw->offloads.vhca_map));1617 WARN_ON(!xa_empty(&esw->offloads.vhca_map));
1621 xa_destroy(&esw->offloads.vhca_map);1618 xa_destroy(&esw->offloads.vhca_map);
@@ -1893,17 +1890,6 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) · 271 unmodified lines
1893}1890}
1894EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);1891EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
1895 1892
1896bool 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
1907bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,1893bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
1908 struct mlx5_core_dev *dev1)1894 struct mlx5_core_dev *dev1)
1909{1895{
@@ -2014,17 +2000,6 @@ void mlx5_esw_unlock(struct mlx5_eswitch *esw) · 104 unmodified lines
2014 up_write(&esw->mode_lock);2000 up_write(&esw->mode_lock);
2015}2001}
2016 2002
2017/**
2018 * mlx5_esw_lock() - Take write lock on esw mode lock
2019 * @esw: eswitch device.
2020 */
2021void mlx5_esw_lock(struct mlx5_eswitch *esw)
2022{
2023 if (!mlx5_esw_allowed(esw))
2024 return;
2025 down_write(&esw->mode_lock);
2026}
2027
2028/**2003/**
2029 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch2004 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
2030 *2005 *
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h+0−8
@@ -331,7 +331,6 @@ struct mlx5_eswitch { · 330 unmodified lines
331 u32 large_group_num;331 u32 large_group_num;
332 } params;332 } params;
333 struct blocking_notifier_head n_head;333 struct blocking_notifier_head n_head;
334 struct lock_class_key mode_lock_key;
335};334};
336 335
337void esw_offloads_disable(struct mlx5_eswitch *esw);336void 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
518 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan_2);517 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan_2);
519}518}
520 519
521bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0,
522 struct mlx5_core_dev *dev1);
523bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,520bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
524 struct mlx5_core_dev *dev1);521 struct mlx5_core_dev *dev1);
525 522
@@ -706,7 +703,6 @@ void mlx5_esw_get(struct mlx5_core_dev *dev); · 180 unmodified lines
706void mlx5_esw_put(struct mlx5_core_dev *dev);703void mlx5_esw_put(struct mlx5_core_dev *dev);
707int mlx5_esw_try_lock(struct mlx5_eswitch *esw);704int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
708void mlx5_esw_unlock(struct mlx5_eswitch *esw);705void mlx5_esw_unlock(struct mlx5_eswitch *esw);
709void mlx5_esw_lock(struct mlx5_eswitch *esw);
710 706
711void esw_vport_change_handle_locked(struct mlx5_vport *vport);707void esw_vport_change_handle_locked(struct mlx5_vport *vport);
712 708
@@ -724,7 +720,6 @@ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } · 11 unmodified lines
724static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}720static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}
725static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }721static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }
726static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf) {}722static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf) {}
727static inline bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1) { return true; }
728static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }723static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
729static inline724static inline
730int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }725int 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
733 return ERR_PTR(-EOPNOTSUPP);728 return ERR_PTR(-EOPNOTSUPP);
734}729}
735 730
736static inline void mlx5_esw_unlock(struct mlx5_eswitch *esw) { return; }
737static inline void mlx5_esw_lock(struct mlx5_eswitch *esw) { return; }
738
739static inline struct mlx5_flow_handle *731static inline struct mlx5_flow_handle *
740esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)732esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
741{733{
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
148 if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {148 if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
149 complete(&fw_reset->done);149 complete(&fw_reset->done);
150 } else {150 } else {
151 mlx5_load_one(dev);151 mlx5_load_one(dev, false);
152 devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0,152 devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0,
153 BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |153 BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
154 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));154 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
6static 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
18static 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
36static 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
57static 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
71static 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
92static 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
130static 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
148DEFINE_SHOW_ATTRIBUTE(type);
149DEFINE_SHOW_ATTRIBUTE(port_sel_mode);
150DEFINE_SHOW_ATTRIBUTE(state);
151DEFINE_SHOW_ATTRIBUTE(flags);
152DEFINE_SHOW_ATTRIBUTE(mapping);
153DEFINE_SHOW_ATTRIBUTE(members);
154
155void 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
170void 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
53 */53 */
54static DEFINE_SPINLOCK(lag_lock);54static DEFINE_SPINLOCK(lag_lock);
55 55
56static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1,56static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, bool shared_fdb, u8 flags)
57 u8 remap_port2, bool shared_fdb, u8 flags)
58{57{
59 u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};58 u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
60 void *lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);59 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
63 62
64 MLX5_SET(lagc, lag_ctx, fdb_selection_mode, shared_fdb);63 MLX5_SET(lagc, lag_ctx, fdb_selection_mode, shared_fdb);
65 if (!(flags & MLX5_LAG_FLAG_HASH_BASED)) {64 if (!(flags & MLX5_LAG_FLAG_HASH_BASED)) {
66 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);65 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
67 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);66 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
68 } else {67 } else {
69 MLX5_SET(lagc, lag_ctx, port_select_mode,68 MLX5_SET(lagc, lag_ctx, port_select_mode,
70 MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT);69 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
73 return mlx5_cmd_exec_in(dev, create_lag, in);72 return mlx5_cmd_exec_in(dev, create_lag, in);
74}73}
75 74
76static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 remap_port1,75static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 num_ports,
77 u8 remap_port2)76 u8 *ports)
78{77{
79 u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};78 u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
80 void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);79 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
82 MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);81 MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
83 MLX5_SET(modify_lag_in, in, field_select, 0x1);82 MLX5_SET(modify_lag_in, in, field_select, 0x1);
84 83
85 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);84 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
86 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);85 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
87 86
88 return mlx5_cmd_exec_in(dev, modify_lag, in);87 return mlx5_cmd_exec_in(dev, modify_lag, in);
89}88}
@@ -108,6 +107,75 @@ int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev) · 18 unmodified lines
108}107}
109EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);108EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
110 109
110static 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
123void 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
139static 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
111static int mlx5_lag_netdev_event(struct notifier_block *this,179static int mlx5_lag_netdev_event(struct notifier_block *this,
112 unsigned long event, void *ptr);180 unsigned long event, void *ptr);
113static void mlx5_do_bond_work(struct work_struct *work);181static void mlx5_do_bond_work(struct work_struct *work);
@@ -121,6 +189,7 @@ static void mlx5_ldev_free(struct kref *ref) · 7 unmodified lines
121 mlx5_lag_mp_cleanup(ldev);189 mlx5_lag_mp_cleanup(ldev);
122 cancel_delayed_work_sync(&ldev->bond_work);190 cancel_delayed_work_sync(&ldev->bond_work);
123 destroy_workqueue(ldev->wq);191 destroy_workqueue(ldev->wq);
192 mutex_destroy(&ldev->lock);
124 kfree(ldev);193 kfree(ldev);
125}194}
126 195
@@ -150,6 +219,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev) · 23 unmodified lines
150 }219 }
151 220
152 kref_init(&ldev->ref);221 kref_init(&ldev->ref);
222 mutex_init(&ldev->lock);
153 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);223 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
154 224
155 ldev->nb.notifier_call = mlx5_lag_netdev_event;225 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
162 if (err)232 if (err)
163 mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",233 mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
164 err);234 err);
235 ldev->ports = MLX5_CAP_GEN(dev, num_lag_ports);
236 ldev->buckets = 1;
165 237
166 return ldev;238 return ldev;
167}239}
@@ -171,7 +243,7 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, · 3 unmodified lines
171{243{
172 int i;244 int i;
173 245
174 for (i = 0; i < MLX5_MAX_PORTS; i++)246 for (i = 0; i < ldev->ports; i++)
175 if (ldev->pf[i].netdev == ndev)247 if (ldev->pf[i].netdev == ndev)
176 return i;248 return i;
177 249
@@ -188,39 +260,72 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev) · 10 unmodified lines
188 return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);260 return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);
189}261}
190 262
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 */
191static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,269static 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)
193{273{
194 bool p1en;274 int disabled[MLX5_MAX_PORTS] = {};
195 bool p2en;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;
196 282
197 p1en = tracker->netdev_state[MLX5_LAG_P1].tx_enabled &&283 for (i = 0; i < num_ports; i++) {
198 tracker->netdev_state[MLX5_LAG_P1].link_up;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 }
199 290
200 p2en = tracker->netdev_state[MLX5_LAG_P2].tx_enabled &&291 /* Use native mapping by default where each port's buckets
201 tracker->netdev_state[MLX5_LAG_P2].link_up;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 }
202 299
203 *port1 = MLX5_LAG_EGRESS_PORT_1;300 /* If all ports are disabled/enabled keep native mapping */
204 *port2 = MLX5_LAG_EGRESS_PORT_2;301 if (enabled_ports_num == num_ports ||
205 if ((!p1en && !p2en) || (p1en && p2en))302 disabled_ports_num == num_ports)
206 return;303 return;
207 304
208 if (p1en)305 /* Go over the disabled ports and for each assign a random active port */
209 *port2 = MLX5_LAG_EGRESS_PORT_1;306 for (i = 0; i < disabled_ports_num; i++) {
210 else307 for (j = 0; j < buckets; j++) {
211 *port1 = MLX5_LAG_EGRESS_PORT_2;308 get_random_bytes(&rand, 4);
309 ports[disabled[i] * buckets + j] = enabled[rand % enabled_ports_num] + 1;
310 }
311 }
212}312}
213 313
214static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev)314static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev)
215{315{
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;
217}322}
218 323
219static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev)324static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev)
220{325{
221 int i;326 int i;
222 327
223 for (i = 0; i < MLX5_MAX_PORTS; i++) {328 for (i = 0; i < ldev->ports; i++) {
224 if (!ldev->pf[i].has_drop)329 if (!ldev->pf[i].has_drop)
225 continue;330 continue;
226 331
@@ -233,12 +338,12 @@ static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev) · 6 unmodified lines
233static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev,338static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev,
234 struct lag_tracker *tracker)339 struct lag_tracker *tracker)
235{340{
236 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;341 u8 disabled_ports[MLX5_MAX_PORTS] = {};
237 struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;342 struct mlx5_core_dev *dev;
238 struct mlx5_core_dev *inactive;343 int disabled_index;
239 u8 v2p_port1, v2p_port2;344 int num_disabled;
240 int inactive_idx;
241 int err;345 int err;
346 int i;
242 347
243 /* First delete the current drop rule so there won't be any dropped348 /* First delete the current drop rule so there won't be any dropped
244 * packets349 * packets
@@ -248,58 +353,60 @@ static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev, · 3 unmodified lines
248 if (!ldev->tracker.has_inactive)353 if (!ldev->tracker.has_inactive)
249 return;354 return;
250 355
251 mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1, &v2p_port2);356 mlx5_infer_tx_disabled(tracker, ldev->ports, disabled_ports, &num_disabled);
252 357
253 if (v2p_port1 == MLX5_LAG_EGRESS_PORT_1) {358 for (i = 0; i < num_disabled; i++) {
254 inactive = dev1;359 disabled_index = disabled_ports[i];
255 inactive_idx = MLX5_LAG_P2;360 dev = ldev->pf[disabled_index].dev;
256 } else {361 err = mlx5_esw_acl_ingress_vport_drop_rule_create(dev->priv.eswitch,
257 inactive = dev0;362 MLX5_VPORT_UPLINK);
258 inactive_idx = MLX5_LAG_P1;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);
259 }368 }
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);
268}369}
269 370
270static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 v2p_port1, u8 v2p_port2)371static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
271{372{
272 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;373 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
273 374
274 if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED)375 if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED)
275 return mlx5_lag_port_sel_modify(ldev, v2p_port1, v2p_port2);376 return mlx5_lag_port_sel_modify(ldev, ports);
276 return mlx5_cmd_modify_lag(dev0, v2p_port1, v2p_port2);377 return mlx5_cmd_modify_lag(dev0, ldev->ports, ports);
277}378}
278 379
279void mlx5_modify_lag(struct mlx5_lag *ldev,380void mlx5_modify_lag(struct mlx5_lag *ldev,
280 struct lag_tracker *tracker)381 struct lag_tracker *tracker)
281{382{
383 u8 ports[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS] = {};
282 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;384 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
283 u8 v2p_port1, v2p_port2;385 int idx;
284 int err;386 int err;
387 int i;
388 int j;
285 389
286 mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1,390 mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ports);
287 &v2p_port2);
288 391
289 if (v2p_port1 != ldev->v2p_map[MLX5_LAG_P1] ||392 for (i = 0; i < ldev->ports; i++) {
290 v2p_port2 != ldev->v2p_map[MLX5_LAG_P2]) {393 for (j = 0; j < ldev->buckets; j++) {
291 err = _mlx5_modify_lag(ldev, v2p_port1, v2p_port2);394 idx = i * ldev->buckets + j;
292 if (err) {395 if (ports[idx] == ldev->v2p_map[idx])
293 mlx5_core_err(dev0,396 continue;
294 "Failed to modify LAG (%d)\n",397 err = _mlx5_modify_lag(ldev, ports);
295 err);398 if (err) {
296 return;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;
297 }409 }
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]);
303 }410 }
304 411
305 if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&412 if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
@@ -307,20 +414,47 @@ void mlx5_modify_lag(struct mlx5_lag *ldev, · 1 unmodified line
307 mlx5_lag_drop_rule_setup(ldev, tracker);414 mlx5_lag_drop_rule_setup(ldev, tracker);
308}415}
309 416
310static void mlx5_lag_set_port_sel_mode(struct mlx5_lag *ldev,417#define MLX5_LAG_ROCE_HASH_PORTS_SUPPORTED 4
311 struct lag_tracker *tracker, u8 *flags)418static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
419 struct lag_tracker *tracker, u8 *flags)
312{420{
313 bool roce_lag = !!(*flags & MLX5_LAG_FLAG_ROCE);
314 struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];421 struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
315 422
316 if (roce_lag ||423 if (ldev->ports == MLX5_LAG_ROCE_HASH_PORTS_SUPPORTED) {
317 !MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) ||424 /* Four ports are support only in hash mode */
318 tracker->tx_type != NETDEV_LAG_TX_TYPE_HASH)425 if (!MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table))
319 return;426 return -EINVAL;
320 *flags |= MLX5_LAG_FLAG_HASH_BASED;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
435static 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
447static 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);
321}455}
322 456
323static char *get_str_port_sel_mode(u8 flags)457char *get_str_port_sel_mode(u8 flags)
324{458{
325 if (flags & MLX5_LAG_FLAG_HASH_BASED)459 if (flags & MLX5_LAG_FLAG_HASH_BASED)
326 return "hash";460 return "hash";
@@ -336,12 +470,11 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, · 9 unmodified lines
336 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};470 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
337 int err;471 int err;
338 472
339 mlx5_core_info(dev0, "lag map port 1:%d port 2:%d shared_fdb:%d mode:%s",473 mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
340 ldev->v2p_map[MLX5_LAG_P1], ldev->v2p_map[MLX5_LAG_P2],474 mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
341 shared_fdb, get_str_port_sel_mode(flags));475 shared_fdb, get_str_port_sel_mode(flags));
342 476
343 err = mlx5_cmd_create_lag(dev0, ldev->v2p_map[MLX5_LAG_P1],477 err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, shared_fdb, flags);
344 ldev->v2p_map[MLX5_LAG_P2], shared_fdb, flags);
345 if (err) {478 if (err) {
346 mlx5_core_err(dev0,479 mlx5_core_err(dev0,
347 "Failed to create LAG (%d)\n",480 "Failed to create LAG (%d)\n",
@@ -377,13 +510,15 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, · 29 unmodified lines
377 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;510 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
378 int err;511 int err;
379 512
380 mlx5_infer_tx_affinity_mapping(tracker, &ldev->v2p_map[MLX5_LAG_P1],513 err = mlx5_lag_set_port_sel_mode(ldev, tracker, &flags);
381 &ldev->v2p_map[MLX5_LAG_P2]);514 if (err)
382 mlx5_lag_set_port_sel_mode(ldev, tracker, &flags);515 return err;
516
517 mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
518
383 if (flags & MLX5_LAG_FLAG_HASH_BASED) {519 if (flags & MLX5_LAG_FLAG_HASH_BASED) {
384 err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,520 err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,
385 ldev->v2p_map[MLX5_LAG_P1],521 ldev->v2p_map);
386 ldev->v2p_map[MLX5_LAG_P2]);
387 if (err) {522 if (err) {
388 mlx5_core_err(dev0,523 mlx5_core_err(dev0,
389 "Failed to create LAG port selection(%d)\n",524 "Failed to create LAG port selection(%d)\n",
@@ -455,25 +590,43 @@ static int mlx5_deactivate_lag(struct mlx5_lag *ldev) · 65 unmodified lines
455 return 0;590 return 0;
456}591}
457 592
593#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2
458static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)594static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
459{595{
460 if (!ldev->pf[MLX5_LAG_P1].dev || !ldev->pf[MLX5_LAG_P2].dev)596#ifdef CONFIG_MLX5_ESWITCH
461 return false;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;
462 604
463#ifdef CONFIG_MLX5_ESWITCH605#ifdef CONFIG_MLX5_ESWITCH
464 return mlx5_esw_lag_prereq(ldev->pf[MLX5_LAG_P1].dev,606 mode = mlx5_eswitch_mode(ldev->pf[MLX5_LAG_P1].dev);
465 ldev->pf[MLX5_LAG_P2].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;
466#else617#else
467 return (!mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P1].dev) &&618 for (i = 0; i < ldev->ports; i++)
468 !mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P2].dev));619 if (mlx5_sriov_is_enabled(ldev->pf[i].dev))
620 return false;
469#endif621#endif
622 return true;
470}623}
471 624
472static void mlx5_lag_add_devices(struct mlx5_lag *ldev)625static void mlx5_lag_add_devices(struct mlx5_lag *ldev)
473{626{
474 int i;627 int i;
475 628
476 for (i = 0; i < MLX5_MAX_PORTS; i++) {629 for (i = 0; i < ldev->ports; i++) {
477 if (!ldev->pf[i].dev)630 if (!ldev->pf[i].dev)
478 continue;631 continue;
479 632
@@ -490,7 +643,7 @@ static void mlx5_lag_remove_devices(struct mlx5_lag *ldev) · 10 unmodified lines
490{643{
491 int i;644 int i;
492 645
493 for (i = 0; i < MLX5_MAX_PORTS; i++) {646 for (i = 0; i < ldev->ports; i++) {
494 if (!ldev->pf[i].dev)647 if (!ldev->pf[i].dev)
495 continue;648 continue;
496 649
@@ -510,6 +663,7 @@ static void mlx5_disable_lag(struct mlx5_lag *ldev) · 13 unmodified lines
510 bool shared_fdb = ldev->shared_fdb;663 bool shared_fdb = ldev->shared_fdb;
511 bool roce_lag;664 bool roce_lag;
512 int err;665 int err;
666 int i;
513 667
514 roce_lag = __mlx5_lag_is_roce(ldev);668 roce_lag = __mlx5_lag_is_roce(ldev);
515 669
@@ -520,7 +674,8 @@ static void mlx5_disable_lag(struct mlx5_lag *ldev) · 4 unmodified lines
520 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;674 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
521 mlx5_rescan_drivers_locked(dev0);675 mlx5_rescan_drivers_locked(dev0);
522 }676 }
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);
524 }679 }
525 680
526 err = mlx5_deactivate_lag(ldev);681 err = mlx5_deactivate_lag(ldev);
@@ -557,6 +712,23 @@ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) · 30 unmodified lines
557 return false;712 return false;
558}713}
559 714
715static 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
560static void mlx5_do_bond(struct mlx5_lag *ldev)732static void mlx5_do_bond(struct mlx5_lag *ldev)
561{733{
562 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;734 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
564 struct lag_tracker tracker;736 struct lag_tracker tracker;
565 bool do_bond, roce_lag;737 bool do_bond, roce_lag;
566 int err;738 int err;
739 int i;
567 740
568 if (!mlx5_lag_is_ready(ldev)) {741 if (!mlx5_lag_is_ready(ldev)) {
569 do_bond = false;742 do_bond = false;
@@ -580,14 +753,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) · 10 unmodified lines
580 if (do_bond && !__mlx5_lag_is_active(ldev)) {753 if (do_bond && !__mlx5_lag_is_active(ldev)) {
581 bool shared_fdb = mlx5_shared_fdb_supported(ldev);754 bool shared_fdb = mlx5_shared_fdb_supported(ldev);
582 755
583 roce_lag = !mlx5_sriov_is_enabled(dev0) &&756 roce_lag = mlx5_lag_is_roce_lag(ldev);
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
591 757
592 if (shared_fdb || roce_lag)758 if (shared_fdb || roce_lag)
593 mlx5_lag_remove_devices(ldev);759 mlx5_lag_remove_devices(ldev);
@@ -604,7 +770,8 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) · 10 unmodified lines
604 } else if (roce_lag) {770 } else if (roce_lag) {
605 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;771 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
606 mlx5_rescan_drivers_locked(dev0);772 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);
608 } else if (shared_fdb) {775 } else if (shared_fdb) {
609 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;776 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
610 mlx5_rescan_drivers_locked(dev0);777 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
636 queue_delayed_work(ldev->wq, &ldev->bond_work, delay);803 queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
637}804}
638 805
639static 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
648static 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
657static void mlx5_do_bond_work(struct work_struct *work)806static void mlx5_do_bond_work(struct work_struct *work)
658{807{
659 struct delayed_work *delayed_work = to_delayed_work(work);808 struct delayed_work *delayed_work = to_delayed_work(work);
660 struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,809 struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
661 bond_work);810 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;
664 int status;811 int status;
665 812
666 status = mlx5_dev_list_trylock();813 status = mlx5_dev_list_trylock();
@@ -669,15 +816,16 @@ static void mlx5_do_bond_work(struct work_struct *work) · 2 unmodified lines
669 return;816 return;
670 }817 }
671 818
819 mutex_lock(&ldev->lock);
672 if (ldev->mode_changes_in_progress) {820 if (ldev->mode_changes_in_progress) {
821 mutex_unlock(&ldev->lock);
673 mlx5_dev_list_unlock();822 mlx5_dev_list_unlock();
674 mlx5_queue_bond_work(ldev, HZ);823 mlx5_queue_bond_work(ldev, HZ);
675 return;824 return;
676 }825 }
677 826
678 mlx5_lag_lock_eswitches(dev0, dev1);
679 mlx5_do_bond(ldev);827 mlx5_do_bond(ldev);
680 mlx5_lag_unlock_eswitches(dev0, dev1);828 mutex_unlock(&ldev->lock);
681 mlx5_dev_list_unlock();829 mlx5_dev_list_unlock();
682}830}
683 831
@@ -691,7 +839,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 7 unmodified lines
691 bool is_bonded, is_in_lag, mode_supported;839 bool is_bonded, is_in_lag, mode_supported;
692 bool has_inactive = 0;840 bool has_inactive = 0;
693 struct slave *slave;841 struct slave *slave;
694 int bond_status = 0;842 u8 bond_status = 0;
695 int num_slaves = 0;843 int num_slaves = 0;
696 int changed = 0;844 int changed = 0;
697 int idx;845 int idx;
@@ -722,7 +870,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 24 unmodified lines
722 rcu_read_unlock();870 rcu_read_unlock();
723 871
724 /* None of this lagdev's netdevs are slaves of this master. */872 /* 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)))
726 return 0;874 return 0;
727 875
728 if (lag_upper_info) {876 if (lag_upper_info) {
@@ -735,7 +883,8 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, · 6 unmodified lines
735 * A device is considered bonded if both its physical ports are slaves883 * A device is considered bonded if both its physical ports are slaves
736 * of the same lag master, and only them.884 * of the same lag master, and only them.
737 */885 */
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);
739 888
740 /* Lag mode must be activebackup or hash. */889 /* Lag mode must be activebackup or hash. */
741 mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP ||890 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
864{1013{
865 unsigned int fn = mlx5_get_dev_index(dev);1014 unsigned int fn = mlx5_get_dev_index(dev);
866 1015
867 if (fn >= MLX5_MAX_PORTS)1016 if (fn >= ldev->ports)
868 return;1017 return;
869 1018
870 spin_lock(&lag_lock);1019 spin_lock(&lag_lock);
@@ -880,7 +1029,7 @@ static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev, · 9 unmodified lines
880 int i;1029 int i;
881 1030
882 spin_lock(&lag_lock);1031 spin_lock(&lag_lock);
883 for (i = 0; i < MLX5_MAX_PORTS; i++) {1032 for (i = 0; i < ldev->ports; i++) {
884 if (ldev->pf[i].netdev == netdev) {1033 if (ldev->pf[i].netdev == netdev) {
885 ldev->pf[i].netdev = NULL;1034 ldev->pf[i].netdev = NULL;
886 break;1035 break;
@@ -894,24 +1043,23 @@ static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev, · 7 unmodified lines
894{1043{
895 unsigned int fn = mlx5_get_dev_index(dev);1044 unsigned int fn = mlx5_get_dev_index(dev);
896 1045
897 if (fn >= MLX5_MAX_PORTS)1046 if (fn >= ldev->ports)
898 return;1047 return;
899 1048
900 ldev->pf[fn].dev = dev;1049 ldev->pf[fn].dev = dev;
901 dev->priv.lag = ldev;1050 dev->priv.lag = ldev;
902}1051}
903 1052
904/* Must be called with intf_mutex held */
905static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,1053static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,
906 struct mlx5_core_dev *dev)1054 struct mlx5_core_dev *dev)
907{1055{
908 int i;1056 int i;
909 1057
910 for (i = 0; i < MLX5_MAX_PORTS; i++)1058 for (i = 0; i < ldev->ports; i++)
911 if (ldev->pf[i].dev == dev)1059 if (ldev->pf[i].dev == dev)
912 break;1060 break;
913 1061
914 if (i == MLX5_MAX_PORTS)1062 if (i == ldev->ports)
915 return;1063 return;
916 1064
917 ldev->pf[i].dev = NULL;1065 ldev->pf[i].dev = NULL;
@@ -924,12 +1072,7 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) · 6 unmodified lines
924 struct mlx5_lag *ldev = NULL;1072 struct mlx5_lag *ldev = NULL;
925 struct mlx5_core_dev *tmp_dev;1073 struct mlx5_core_dev *tmp_dev;
926 1074
927 if (!MLX5_CAP_GEN(dev, vport_group_manager) ||1075 tmp_dev = mlx5_get_next_phys_dev_lag(dev);
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);
933 if (tmp_dev)1076 if (tmp_dev)
934 ldev = tmp_dev->priv.lag;1077 ldev = tmp_dev->priv.lag;
935 1078
@@ -939,13 +1082,18 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev) · 3 unmodified lines
939 mlx5_core_err(dev, "Failed to alloc lag dev\n");1082 mlx5_core_err(dev, "Failed to alloc lag dev\n");
940 return 0;1083 return 0;
941 }1084 }
942 } else {1085 mlx5_ldev_add_mdev(ldev, dev);
943 if (ldev->mode_changes_in_progress)1086 return 0;
944 return -EAGAIN;
945 mlx5_ldev_get(ldev);
946 }1087 }
947 1088
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);
948 mlx5_ldev_add_mdev(ldev, dev);1095 mlx5_ldev_add_mdev(ldev, dev);
1096 mutex_unlock(&ldev->lock);
949 1097
950 return 0;1098 return 0;
951}1099}
@@ -958,15 +1106,19 @@ void mlx5_lag_remove_mdev(struct mlx5_core_dev *dev) · 6 unmodified lines
958 if (!ldev)1106 if (!ldev)
959 return;1107 return;
960 1108
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);
961recheck:1113recheck:
962 mlx5_dev_list_lock();1114 mutex_lock(&ldev->lock);
963 if (ldev->mode_changes_in_progress) {1115 if (ldev->mode_changes_in_progress) {
964 mlx5_dev_list_unlock();1116 mutex_unlock(&ldev->lock);
965 msleep(100);1117 msleep(100);
966 goto recheck;1118 goto recheck;
967 }1119 }
968 mlx5_ldev_remove_mdev(ldev, dev);1120 mlx5_ldev_remove_mdev(ldev, dev);
969 mlx5_dev_list_unlock();1121 mutex_unlock(&ldev->lock);
970 mlx5_ldev_put(ldev);1122 mlx5_ldev_put(ldev);
971}1123}
972 1124
@@ -974,35 +1126,45 @@ void mlx5_lag_add_mdev(struct mlx5_core_dev *dev) · 1 unmodified line
974{1126{
975 int err;1127 int err;
976 1128
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
977recheck:1135recheck:
978 mlx5_dev_list_lock();1136 mlx5_dev_list_lock();
979 err = __mlx5_lag_dev_add_mdev(dev);1137 err = __mlx5_lag_dev_add_mdev(dev);
1138 mlx5_dev_list_unlock();
1139
980 if (err) {1140 if (err) {
981 mlx5_dev_list_unlock();
982 msleep(100);1141 msleep(100);
983 goto recheck;1142 goto recheck;
984 }1143 }
985 mlx5_dev_list_unlock();1144 mlx5_ldev_add_debugfs(dev);
986}1145}
987 1146
988/* Must be called with intf_mutex held */
989void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,1147void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,
990 struct net_device *netdev)1148 struct net_device *netdev)
991{1149{
992 struct mlx5_lag *ldev;1150 struct mlx5_lag *ldev;
1151 bool lag_is_active;
993 1152
994 ldev = mlx5_lag_dev(dev);1153 ldev = mlx5_lag_dev(dev);
995 if (!ldev)1154 if (!ldev)
996 return;1155 return;
997 1156
1157 mutex_lock(&ldev->lock);
998 mlx5_ldev_remove_netdev(ldev, netdev);1158 mlx5_ldev_remove_netdev(ldev, netdev);
999 ldev->flags &= ~MLX5_LAG_FLAG_READY;1159 ldev->flags &= ~MLX5_LAG_FLAG_READY;
1000 1160
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)
1002 mlx5_queue_bond_work(ldev, 0);1165 mlx5_queue_bond_work(ldev, 0);
1003}1166}
1004 1167
1005/* Must be called with intf_mutex held */
1006void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,1168void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
1007 struct net_device *netdev)1169 struct net_device *netdev)
1008{1170{
@@ -1013,14 +1175,16 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev, · 4 unmodified lines
1013 if (!ldev)1175 if (!ldev)
1014 return;1176 return;
1015 1177
1178 mutex_lock(&ldev->lock);
1016 mlx5_ldev_add_netdev(ldev, dev, netdev);1179 mlx5_ldev_add_netdev(ldev, dev, netdev);
1017 1180
1018 for (i = 0; i < MLX5_MAX_PORTS; i++)1181 for (i = 0; i < ldev->ports; i++)
1019 if (!ldev->pf[i].dev)1182 if (!ldev->pf[i].dev)
1020 break;1183 break;
1021 1184
1022 if (i >= MLX5_MAX_PORTS)1185 if (i >= ldev->ports)
1023 ldev->flags |= MLX5_LAG_FLAG_READY;1186 ldev->flags |= MLX5_LAG_FLAG_READY;
1187 mutex_unlock(&ldev->lock);
1024 mlx5_queue_bond_work(ldev, 0);1188 mlx5_queue_bond_work(ldev, 0);
1025}1189}
1026 1190
@@ -1097,8 +1261,6 @@ EXPORT_SYMBOL(mlx5_lag_is_shared_fdb); · 70 unmodified lines
1097 1261
1098void mlx5_lag_disable_change(struct mlx5_core_dev *dev)1262void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
1099{1263{
1100 struct mlx5_core_dev *dev0;
1101 struct mlx5_core_dev *dev1;
1102 struct mlx5_lag *ldev;1264 struct mlx5_lag *ldev;
1103 1265
1104 ldev = mlx5_lag_dev(dev);1266 ldev = mlx5_lag_dev(dev);
@@ -1106,16 +1268,13 @@ void mlx5_lag_disable_change(struct mlx5_core_dev *dev) · 1 unmodified line
1106 return;1268 return;
1107 1269
1108 mlx5_dev_list_lock();1270 mlx5_dev_list_lock();
1109 1271 mutex_lock(&ldev->lock);
1110 dev0 = ldev->pf[MLX5_LAG_P1].dev;
1111 dev1 = ldev->pf[MLX5_LAG_P2].dev;
1112 1272
1113 ldev->mode_changes_in_progress++;1273 ldev->mode_changes_in_progress++;
1114 if (__mlx5_lag_is_active(ldev)) {1274 if (__mlx5_lag_is_active(ldev))
1115 mlx5_lag_lock_eswitches(dev0, dev1);
1116 mlx5_disable_lag(ldev);1275 mlx5_disable_lag(ldev);
1117 mlx5_lag_unlock_eswitches(dev0, dev1);1276
1118 }1277 mutex_unlock(&ldev->lock);
1119 mlx5_dev_list_unlock();1278 mlx5_dev_list_unlock();
1120}1279}
1121 1280
@@ -1127,9 +1286,9 @@ void mlx5_lag_enable_change(struct mlx5_core_dev *dev) · 5 unmodified lines
1127 if (!ldev)1286 if (!ldev)
1128 return;1287 return;
1129 1288
1130 mlx5_dev_list_lock();1289 mutex_lock(&ldev->lock);
1131 ldev->mode_changes_in_progress--;1290 ldev->mode_changes_in_progress--;
1132 mlx5_dev_list_unlock();1291 mutex_unlock(&ldev->lock);
1133 mlx5_queue_bond_work(ldev, 0);1292 mlx5_queue_bond_work(ldev, 0);
1134}1293}
1135 1294
@@ -1137,6 +1296,7 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev) · 1 unmodified line
1137{1296{
1138 struct net_device *ndev = NULL;1297 struct net_device *ndev = NULL;
1139 struct mlx5_lag *ldev;1298 struct mlx5_lag *ldev;
1299 int i;
1140 1300
1141 spin_lock(&lag_lock);1301 spin_lock(&lag_lock);
1142 ldev = mlx5_lag_dev(dev);1302 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
1145 goto unlock;1305 goto unlock;
1146 1306
1147 if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {1307 if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
1148 ndev = ldev->tracker.netdev_state[MLX5_LAG_P1].tx_enabled ?1308 for (i = 0; i < ldev->ports; i++)
1149 ldev->pf[MLX5_LAG_P1].netdev :1309 if (ldev->tracker.netdev_state[i].tx_enabled)
1150 ldev->pf[MLX5_LAG_P2].netdev;1310 ndev = ldev->pf[i].netdev;
1311 if (!ndev)
1312 ndev = ldev->pf[ldev->ports - 1].netdev;
1151 } else {1313 } else {
1152 ndev = ldev->pf[MLX5_LAG_P1].netdev;1314 ndev = ldev->pf[MLX5_LAG_P1].netdev;
1153 }1315 }
@@ -1166,18 +1328,21 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev, · 12 unmodified lines
1166{1328{
1167 struct mlx5_lag *ldev;1329 struct mlx5_lag *ldev;
1168 u8 port = 0;1330 u8 port = 0;
1331 int i;
1169 1332
1170 spin_lock(&lag_lock);1333 spin_lock(&lag_lock);
1171 ldev = mlx5_lag_dev(dev);1334 ldev = mlx5_lag_dev(dev);
1172 if (!(ldev && __mlx5_lag_is_roce(ldev)))1335 if (!(ldev && __mlx5_lag_is_roce(ldev)))
1173 goto unlock;1336 goto unlock;
1174 1337
1175 if (ldev->pf[MLX5_LAG_P1].netdev == slave)1338 for (i = 0; i < ldev->ports; i++) {
1176 port = MLX5_LAG_P1;1339 if (ldev->pf[MLX5_LAG_P1].netdev == slave) {
1177 else1340 port = i;
1178 port = MLX5_LAG_P2;1341 break;
1342 }
1343 }
1179 1344
1180 port = ldev->v2p_map[port];1345 port = ldev->v2p_map[port * ldev->buckets];
1181 1346
1182unlock:1347unlock:
1183 spin_unlock(&lag_lock);1348 spin_unlock(&lag_lock);
@@ -1185,6 +1350,18 @@ unlock: · 1 unmodified line
1185}1350}
1186EXPORT_SYMBOL(mlx5_lag_get_slave_port);1351EXPORT_SYMBOL(mlx5_lag_get_slave_port);
1187 1352
1353u8 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}
1363EXPORT_SYMBOL(mlx5_lag_get_num_ports);
1364
1188struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)1365struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
1189{1366{
1190 struct mlx5_core_dev *peer_dev = NULL;1367 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
1211 size_t *offsets)1388 size_t *offsets)
1212{1389{
1213 int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);1390 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;
1215 struct mlx5_lag *ldev;1392 struct mlx5_lag *ldev;
1216 int num_ports;1393 int num_ports;
1217 int ret, i, j;1394 int ret, i, j;
@@ -1221,14 +1398,20 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 3 unmodified lines
1221 if (!out)1398 if (!out)
1222 return -ENOMEM;1399 return -ENOMEM;
1223 1400
1401 mdev = kvzalloc(sizeof(mdev[0]) * MLX5_MAX_PORTS, GFP_KERNEL);
1402 if (!mdev) {
1403 ret = -ENOMEM;
1404 goto free_out;
1405 }
1406
1224 memset(values, 0, sizeof(*values) * num_counters);1407 memset(values, 0, sizeof(*values) * num_counters);
1225 1408
1226 spin_lock(&lag_lock);1409 spin_lock(&lag_lock);
1227 ldev = mlx5_lag_dev(dev);1410 ldev = mlx5_lag_dev(dev);
1228 if (ldev && __mlx5_lag_is_active(ldev)) {1411 if (ldev && __mlx5_lag_is_active(ldev)) {
1229 num_ports = MLX5_MAX_PORTS;1412 num_ports = ldev->ports;
1230 mdev[MLX5_LAG_P1] = ldev->pf[MLX5_LAG_P1].dev;1413 for (i = 0; i < ldev->ports; i++)
1231 mdev[MLX5_LAG_P2] = ldev->pf[MLX5_LAG_P2].dev;1414 mdev[i] = ldev->pf[i].dev;
1232 } else {1415 } else {
1233 num_ports = 1;1416 num_ports = 1;
1234 mdev[MLX5_LAG_P1] = dev;1417 mdev[MLX5_LAG_P1] = dev;
@@ -1243,13 +1426,15 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 8 unmodified lines
1243 ret = mlx5_cmd_exec_inout(mdev[i], query_cong_statistics, in,1426 ret = mlx5_cmd_exec_inout(mdev[i], query_cong_statistics, in,
1244 out);1427 out);
1245 if (ret)1428 if (ret)
1246 goto free;1429 goto free_mdev;
1247 1430
1248 for (j = 0; j < num_counters; ++j)1431 for (j = 0; j < num_counters; ++j)
1249 values[j] += be64_to_cpup((__be64 *)(out + offsets[j]));1432 values[j] += be64_to_cpup((__be64 *)(out + offsets[j]));
1250 }1433 }
1251 1434
1252free:1435free_mdev:
1436 kvfree(mdev);
1437free_out:
1253 kvfree(out);1438 kvfree(out);
1254 return ret;1439 return ret;
1255}1440}
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h+15−1
@@ -4,6 +4,9 @@ · 3 unmodified lines
4#ifndef __MLX5_LAG_H__4#ifndef __MLX5_LAG_H__
5#define __MLX5_LAG_H__5#define __MLX5_LAG_H__
6 6
7#include <linux/debugfs.h>
8
9#define MLX5_LAG_MAX_HASH_BUCKETS 16
7#include "mlx5_core.h"10#include "mlx5_core.h"
8#include "mp.h"11#include "mp.h"
9#include "port_sel.h"12#include "port_sel.h"
@@ -45,9 +48,11 @@ struct lag_tracker { · 35 unmodified lines
45 */48 */
46struct mlx5_lag {49struct mlx5_lag {
47 u8 flags;50 u8 flags;
51 u8 ports;
52 u8 buckets;
48 int mode_changes_in_progress;53 int mode_changes_in_progress;
49 bool shared_fdb;54 bool shared_fdb;
50 u8 v2p_map[MLX5_MAX_PORTS];55 u8 v2p_map[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS];
51 struct kref ref;56 struct kref ref;
52 struct lag_func pf[MLX5_MAX_PORTS];57 struct lag_func pf[MLX5_MAX_PORTS];
53 struct lag_tracker tracker;58 struct lag_tracker tracker;
@@ -56,6 +61,8 @@ struct mlx5_lag { · 2 unmodified lines
56 struct notifier_block nb;61 struct notifier_block nb;
57 struct lag_mp lag_mp;62 struct lag_mp lag_mp;
58 struct mlx5_lag_port_sel port_sel;63 struct mlx5_lag_port_sel port_sel;
64 /* Protect lag fields/state changes */
65 struct mutex lock;
59};66};
60 67
61static inline struct mlx5_lag *68static inline struct mlx5_lag *
@@ -85,4 +92,11 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, · 23 unmodified lines
85int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,92int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
86 struct net_device *ndev);93 struct net_device *ndev);
87 94
95char *get_str_port_sel_mode(u8 flags);
96void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
97 u8 *ports, int *num_enabled);
98
99void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev);
100void mlx5_ldev_remove_debugfs(struct dentry *dbg);
101
88#endif /* __MLX5_LAG_H__ */102#endif /* __MLX5_LAG_H__ */
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c+77−52
@@ -12,7 +12,8 @@ enum { · 11 unmodified lines
12 12
13static struct mlx5_flow_group *13static struct mlx5_flow_group *
14mlx5_create_hash_flow_group(struct mlx5_flow_table *ft,14mlx5_create_hash_flow_group(struct mlx5_flow_table *ft,
15 struct mlx5_flow_definer *definer)15 struct mlx5_flow_definer *definer,
16 u8 rules)
16{17{
17 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);18 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
18 struct mlx5_flow_group *fg;19 struct mlx5_flow_group *fg;
@@ -25,7 +26,7 @@ mlx5_create_hash_flow_group(struct mlx5_flow_table *ft, · 6 unmodified lines
25 MLX5_SET(create_flow_group_in, in, match_definer_id,26 MLX5_SET(create_flow_group_in, in, match_definer_id,
26 mlx5_get_match_definer_id(definer));27 mlx5_get_match_definer_id(definer));
27 MLX5_SET(create_flow_group_in, in, start_flow_index, 0);28 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);
29 MLX5_SET(create_flow_group_in, in, group_type,30 MLX5_SET(create_flow_group_in, in, group_type,
30 MLX5_CREATE_FLOW_GROUP_IN_GROUP_TYPE_HASH_SPLIT);31 MLX5_CREATE_FLOW_GROUP_IN_GROUP_TYPE_HASH_SPLIT);
31 32
@@ -36,7 +37,7 @@ mlx5_create_hash_flow_group(struct mlx5_flow_table *ft, · 4 unmodified lines
36 37
37static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,38static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
38 struct mlx5_lag_definer *lag_definer,39 struct mlx5_lag_definer *lag_definer,
39 u8 port1, u8 port2)40 u8 *ports)
40{41{
41 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;42 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
42 struct mlx5_flow_table_attr ft_attr = {};43 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
44 MLX5_DECLARE_FLOW_ACT(flow_act);45 MLX5_DECLARE_FLOW_ACT(flow_act);
45 struct mlx5_flow_namespace *ns;46 struct mlx5_flow_namespace *ns;
46 int err, i;47 int err, i;
48 int idx;
49 int j;
47 50
48 ft_attr.max_fte = MLX5_MAX_PORTS;51 ft_attr.max_fte = ldev->ports * ldev->buckets;
49 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;52 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;
50 53
51 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_PORT_SEL);54 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
61 }64 }
62 65
63 lag_definer->fg = mlx5_create_hash_flow_group(lag_definer->ft,66 lag_definer->fg = mlx5_create_hash_flow_group(lag_definer->ft,
64 lag_definer->definer);67 lag_definer->definer,
68 ft_attr.max_fte);
65 if (IS_ERR(lag_definer->fg)) {69 if (IS_ERR(lag_definer->fg)) {
66 err = PTR_ERR(lag_definer->fg);70 err = PTR_ERR(lag_definer->fg);
67 goto destroy_ft;71 goto destroy_ft;
@@ -70,19 +74,25 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, · 2 unmodified lines
70 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;74 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
71 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;75 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
72 flow_act.flags |= FLOW_ACT_NO_APPEND;76 flow_act.flags |= FLOW_ACT_NO_APPEND;
73 for (i = 0; i < MLX5_MAX_PORTS; i++) {77 for (i = 0; i < ldev->ports; i++) {
74 u8 affinity = i == 0 ? port1 : port2;78 for (j = 0; j < ldev->buckets; j++) {
75 79 u8 affinity;
76 dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev,80
77 vhca_id);81 idx = i * ldev->buckets + j;
78 lag_definer->rules[i] = mlx5_add_flow_rules(lag_definer->ft,82 affinity = ports[idx];
79 NULL, &flow_act,83
80 &dest, 1);84 dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev,
81 if (IS_ERR(lag_definer->rules[i])) {85 vhca_id);
82 err = PTR_ERR(lag_definer->rules[i]);86 lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft,
83 while (i--)87 NULL, &flow_act,
84 mlx5_del_flow_rules(lag_definer->rules[i]);88 &dest, 1);
85 goto destroy_fg;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 }
86 }96 }
87 }97 }
88 98
@@ -279,8 +289,7 @@ static int mlx5_lag_set_definer(u32 *match_definer_mask, · 190 unmodified lines
279 289
280static struct mlx5_lag_definer *290static struct mlx5_lag_definer *
281mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,291mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
282 enum mlx5_traffic_types tt, bool tunnel, u8 port1,292 enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
283 u8 port2)
284{293{
285 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;294 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
286 struct mlx5_lag_definer *lag_definer;295 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
308 goto free_mask;317 goto free_mask;
309 }318 }
310 319
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);
312 if (err)321 if (err)
313 goto destroy_match_definer;322 goto destroy_match_definer;
314 323
@@ -329,10 +338,16 @@ static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev, · 14 unmodified lines
329 struct mlx5_lag_definer *lag_definer)338 struct mlx5_lag_definer *lag_definer)
330{339{
331 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;340 struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
341 int idx;
332 int i;342 int i;
343 int j;
333 344
334 for (i = 0; i < MLX5_MAX_PORTS; i++)345 for (i = 0; i < ldev->ports; i++) {
335 mlx5_del_flow_rules(lag_definer->rules[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 }
336 mlx5_destroy_flow_group(lag_definer->fg);351 mlx5_destroy_flow_group(lag_definer->fg);
337 mlx5_destroy_flow_table(lag_definer->ft);352 mlx5_destroy_flow_table(lag_definer->ft);
338 mlx5_destroy_match_definer(dev, lag_definer->definer);353 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
356 371
357static int mlx5_lag_create_definers(struct mlx5_lag *ldev,372static int mlx5_lag_create_definers(struct mlx5_lag *ldev,
358 enum netdev_lag_hash hash_type,373 enum netdev_lag_hash hash_type,
359 u8 port1, u8 port2)374 u8 *ports)
360{375{
361 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;376 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
362 struct mlx5_lag_definer *lag_definer;377 struct mlx5_lag_definer *lag_definer;
@@ -364,7 +379,7 @@ static int mlx5_lag_create_definers(struct mlx5_lag *ldev, · 1 unmodified line
364 379
365 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {380 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
366 lag_definer = mlx5_lag_create_definer(ldev, hash_type, tt,381 lag_definer = mlx5_lag_create_definer(ldev, hash_type, tt,
367 false, port1, port2);382 false, ports);
368 if (IS_ERR(lag_definer)) {383 if (IS_ERR(lag_definer)) {
369 err = PTR_ERR(lag_definer);384 err = PTR_ERR(lag_definer);
370 goto destroy_definers;385 goto destroy_definers;
@@ -376,7 +391,7 @@ static int mlx5_lag_create_definers(struct mlx5_lag *ldev, · 5 unmodified lines
376 391
377 lag_definer =392 lag_definer =
378 mlx5_lag_create_definer(ldev, hash_type, tt,393 mlx5_lag_create_definer(ldev, hash_type, tt,
379 true, port1, port2);394 true, ports);
380 if (IS_ERR(lag_definer)) {395 if (IS_ERR(lag_definer)) {
381 err = PTR_ERR(lag_definer);396 err = PTR_ERR(lag_definer);
382 goto destroy_definers;397 goto destroy_definers;
@@ -513,13 +528,13 @@ static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev) · 130 unmodified lines
513}528}
514 529
515int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,530int 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)
517{532{
518 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;533 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
519 int err;534 int err;
520 535
521 set_tt_map(port_sel, hash_type);536 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);
523 if (err)538 if (err)
524 return err;539 return err;
525 540
@@ -543,52 +558,62 @@ destroy_definers: · 17 unmodified lines
543 return err;558 return err;
544}559}
545 560
546static int561static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
547mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,562 struct mlx5_lag_definer *def,
548 struct mlx5_lag_definer **definers,563 u8 *ports)
549 u8 port1, u8 port2)
550{564{
551 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
552 struct mlx5_flow_destination dest = {};565 struct mlx5_flow_destination dest = {};
566 int idx;
553 int err;567 int err;
554 int tt;568 int i;
569 int j;
555 570
556 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;571 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
557 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;572 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
558 573
559 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {574 for (i = 0; i < ldev->ports; i++) {
560 struct mlx5_flow_handle **rules = definers[tt]->rules;575 for (j = 0; j < ldev->buckets; j++) {
576 idx = i * ldev->buckets + j;
577 if (ldev->v2p_map[i] == ports[i])
578 continue;
561 579
562 if (ldev->v2p_map[MLX5_LAG_P1] != port1) {580 dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
563 dest.vport.vhca_id =581 vhca_id);
564 MLX5_CAP_GEN(ldev->pf[port1 - 1].dev, vhca_id);582 err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL);
565 err = mlx5_modify_rule_destination(rules[MLX5_LAG_P1],
566 &dest, NULL);
567 if (err)583 if (err)
568 return err;584 return err;
569 }585 }
586 }
570 587
571 if (ldev->v2p_map[MLX5_LAG_P2] != port2) {588 return 0;
572 dest.vport.vhca_id =589}
573 MLX5_CAP_GEN(ldev->pf[port2 - 1].dev, vhca_id);590
574 err = mlx5_modify_rule_destination(rules[MLX5_LAG_P2],591static int
575 &dest, NULL);592mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
576 if (err)593 struct mlx5_lag_definer **definers,
577 return err;594 u8 *ports)
578 }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;
579 }604 }
580 605
581 return 0;606 return 0;
582}607}
583 608
584int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2)609int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
585{610{
586 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;611 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
587 int err;612 int err;
588 613
589 err = mlx5_lag_modify_definers_destinations(ldev,614 err = mlx5_lag_modify_definers_destinations(ldev,
590 port_sel->outer.definers,615 port_sel->outer.definers,
591 port1, port2);616 ports);
592 if (err)617 if (err)
593 return err;618 return err;
594 619
@@ -597,7 +622,7 @@ int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2) · 2 unmodified lines
597 622
598 return mlx5_lag_modify_definers_destinations(ldev,623 return mlx5_lag_modify_definers_destinations(ldev,
599 port_sel->inner.definers,624 port_sel->inner.definers,
600 port1, port2);625 ports);
601}626}
602 627
603void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev)628void 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
10 struct mlx5_flow_definer *definer;10 struct mlx5_flow_definer *definer;
11 struct mlx5_flow_table *ft;11 struct mlx5_flow_table *ft;
12 struct mlx5_flow_group *fg;12 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];
14};17};
15 18
16struct mlx5_lag_ttc {19struct mlx5_lag_ttc {
@@ -27,22 +30,20 @@ struct mlx5_lag_port_sel { · 10 unmodified lines
27 30
28#ifdef CONFIG_MLX5_ESWITCH31#ifdef CONFIG_MLX5_ESWITCH
29 32
30int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1, u8 port2);33int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports);
31void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev);34void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev);
32int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,35int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
33 enum netdev_lag_hash hash_type, u8 port1,36 enum netdev_lag_hash hash_type, u8 *ports);
34 u8 port2);
35 37
36#else /* CONFIG_MLX5_ESWITCH */38#else /* CONFIG_MLX5_ESWITCH */
37static inline int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,39static inline int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
38 enum netdev_lag_hash hash_type,40 enum netdev_lag_hash hash_type,
39 u8 port1, u8 port2)41 u8 *ports)
40{42{
41 return 0;43 return 0;
42}44}
43 45
44static inline int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 port1,46static inline int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
45 u8 port2)
46{47{
47 return 0;48 return 0;
48}49}
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c+9−7
@@ -14,7 +14,7 @@ static LIST_HEAD(devcom_list); · 13 unmodified lines
14struct mlx5_devcom_component {14struct mlx5_devcom_component {
15 struct {15 struct {
16 void *data;16 void *data;
17 } device[MLX5_MAX_PORTS];17 } device[MLX5_DEVCOM_PORTS_SUPPORTED];
18 18
19 mlx5_devcom_event_handler_t handler;19 mlx5_devcom_event_handler_t handler;
20 struct rw_semaphore sem;20 struct rw_semaphore sem;
@@ -25,7 +25,7 @@ struct mlx5_devcom_list { · 4 unmodified lines
25 struct list_head list;25 struct list_head list;
26 26
27 struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS];27 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];
29};29};
30 30
31struct mlx5_devcom {31struct mlx5_devcom {
@@ -74,13 +74,15 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) · 42 unmodified lines
74 74
75 if (!mlx5_core_is_pf(dev))75 if (!mlx5_core_is_pf(dev))
76 return NULL;76 return NULL;
77 if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
78 return NULL;
77 79
78 sguid0 = mlx5_query_nic_system_image_guid(dev);80 sguid0 = mlx5_query_nic_system_image_guid(dev);
79 list_for_each_entry(iter, &devcom_list, list) {81 list_for_each_entry(iter, &devcom_list, list) {
80 struct mlx5_core_dev *tmp_dev = NULL;82 struct mlx5_core_dev *tmp_dev = NULL;
81 83
82 idx = -1;84 idx = -1;
83 for (i = 0; i < MLX5_MAX_PORTS; i++) {85 for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
84 if (iter->devs[i])86 if (iter->devs[i])
85 tmp_dev = iter->devs[i];87 tmp_dev = iter->devs[i];
86 else88 else
@@ -134,11 +136,11 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom) · 47 unmodified lines
134 136
135 kfree(devcom);137 kfree(devcom);
136 138
137 for (i = 0; i < MLX5_MAX_PORTS; i++)139 for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
138 if (priv->devs[i])140 if (priv->devs[i])
139 break;141 break;
140 142
141 if (i != MLX5_MAX_PORTS)143 if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
142 return;144 return;
143 145
144 list_del(&priv->list);146 list_del(&priv->list);
@@ -191,7 +193,7 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom, · 46 unmodified lines
191 193
192 comp = &devcom->priv->components[id];194 comp = &devcom->priv->components[id];
193 down_write(&comp->sem);195 down_write(&comp->sem);
194 for (i = 0; i < MLX5_MAX_PORTS; i++)196 for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
195 if (i != devcom->idx && comp->device[i].data) {197 if (i != devcom->idx && comp->device[i].data) {
196 err = comp->handler(event, comp->device[i].data,198 err = comp->handler(event, comp->device[i].data,
197 event_data);199 event_data);
@@ -239,7 +241,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, · 41 unmodified lines
239 return NULL;241 return NULL;
240 }242 }
241 243
242 for (i = 0; i < MLX5_MAX_PORTS; i++)244 for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
243 if (i != devcom->idx)245 if (i != devcom->idx)
244 break;246 break;
245 247
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h+2−0
@@ -6,6 +6,8 @@ · 5 unmodified lines
6 6
7#include <linux/mlx5/driver.h>7#include <linux/mlx5/driver.h>
8 8
9#define MLX5_DEVCOM_PORTS_SUPPORTED 2
10
9enum mlx5_devcom_components {11enum mlx5_devcom_components {
10 MLX5_DEVCOM_ESW_OFFLOADS,12 MLX5_DEVCOM_ESW_OFFLOADS,
11 13
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c+1−0
@@ -10,6 +10,7 @@ struct mlx5_timeouts { · 9 unmodified lines
10 10
11static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {11static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {
12 [MLX5_TO_FW_PRE_INIT_TIMEOUT_MS] = 120000,12 [MLX5_TO_FW_PRE_INIT_TIMEOUT_MS] = 120000,
13 [MLX5_TO_FW_PRE_INIT_ON_RECOVERY_TIMEOUT_MS] = 7200000,
13 [MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS] = 20000,14 [MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS] = 20000,
14 [MLX5_TO_FW_PRE_INIT_WAIT_MS] = 2,15 [MLX5_TO_FW_PRE_INIT_WAIT_MS] = 2,
15 [MLX5_TO_FW_INIT_MS] = 2000,16 [MLX5_TO_FW_INIT_MS] = 2000,
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h+1−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
7enum mlx5_timeouts_types {7enum mlx5_timeouts_types {
8 /* pre init timeouts (not read from FW) */8 /* pre init timeouts (not read from FW) */
9 MLX5_TO_FW_PRE_INIT_TIMEOUT_MS,9 MLX5_TO_FW_PRE_INIT_TIMEOUT_MS,
10 MLX5_TO_FW_PRE_INIT_ON_RECOVERY_TIMEOUT_MS,
10 MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS,11 MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS,
11 MLX5_TO_FW_PRE_INIT_WAIT_MS,12 MLX5_TO_FW_PRE_INIT_WAIT_MS,
12 13
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
189 fw_initializing = ioread32be(&dev->iseg->initializing);189 fw_initializing = ioread32be(&dev->iseg->initializing);
190 if (!(fw_initializing >> 31))190 if (!(fw_initializing >> 31))
191 break;191 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)) {
193 err = -EBUSY;194 err = -EBUSY;
194 break;195 break;
195 }196 }
@@ -1002,7 +1003,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) · 806 unmodified lines
1002 mlx5_devcom_unregister_device(dev->priv.devcom);1003 mlx5_devcom_unregister_device(dev->priv.devcom);
1003}1004}
1004 1005
1005static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot)1006static int mlx5_function_setup(struct mlx5_core_dev *dev, u64 timeout)
1006{1007{
1007 int err;1008 int err;
1008 1009
@@ -1017,11 +1018,11 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) · 8 unmodified lines
1017 1018
1018 /* wait for firmware to accept initialization segments configurations1019 /* wait for firmware to accept initialization segments configurations
1019 */1020 */
1020 err = wait_fw_init(dev, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT),1021 err = wait_fw_init(dev, timeout,
1021 mlx5_tout_ms(dev, FW_PRE_INIT_WARN_MESSAGE_INTERVAL));1022 mlx5_tout_ms(dev, FW_PRE_INIT_WARN_MESSAGE_INTERVAL));
1022 if (err) {1023 if (err) {
1023 mlx5_core_err(dev, "Firmware over %llu MS in pre-initializing state, aborting\n",1024 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);
1025 return err;1026 return err;
1026 }1027 }
1027 1028
@@ -1271,7 +1272,7 @@ int mlx5_init_one(struct mlx5_core_dev *dev) · 243 unmodified lines
1271 mutex_lock(&dev->intf_state_mutex);1272 mutex_lock(&dev->intf_state_mutex);
1272 dev->state = MLX5_DEVICE_STATE_UP;1273 dev->state = MLX5_DEVICE_STATE_UP;
1273 1274
1274 err = mlx5_function_setup(dev, true);1275 err = mlx5_function_setup(dev, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
1275 if (err)1276 if (err)
1276 goto err_function;1277 goto err_function;
1277 1278
@@ -1335,9 +1336,10 @@ out: · 57 unmodified lines
1335 mutex_unlock(&dev->intf_state_mutex);1336 mutex_unlock(&dev->intf_state_mutex);
1336}1337}
1337 1338
1338int mlx5_load_one(struct mlx5_core_dev *dev)1339int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery)
1339{1340{
1340 int err = 0;1341 int err = 0;
1342 u64 timeout;
1341 1343
1342 mutex_lock(&dev->intf_state_mutex);1344 mutex_lock(&dev->intf_state_mutex);
1343 if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {1345 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
1347 /* remove any previous indication of internal error */1349 /* remove any previous indication of internal error */
1348 dev->state = MLX5_DEVICE_STATE_UP;1350 dev->state = MLX5_DEVICE_STATE_UP;
1349 1351
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);
1351 if (err)1357 if (err)
1352 goto err_function;1358 goto err_function;
1353 1359
@@ -1602,6 +1608,7 @@ static void remove_one(struct pci_dev *pdev) · 248 unmodified lines
1602 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);1608 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1603 struct devlink *devlink = priv_to_devlink(dev);1609 struct devlink *devlink = priv_to_devlink(dev);
1604 1610
1611 set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
1605 devlink_unregister(devlink);1612 devlink_unregister(devlink);
1606 mlx5_sriov_disable(pdev);1613 mlx5_sriov_disable(pdev);
1607 mlx5_crdump_disable(dev);1614 mlx5_crdump_disable(dev);
@@ -1717,7 +1724,7 @@ static void mlx5_pci_resume(struct pci_dev *pdev) · 109 unmodified lines
1717 1724
1718 mlx5_pci_trace(dev, "Enter, loading driver..\n");1725 mlx5_pci_trace(dev, "Enter, loading driver..\n");
1719 1726
1720 err = mlx5_load_one(dev);1727 err = mlx5_load_one(dev, false);
1721 1728
1722 mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err,1729 mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err,
1723 !err ? "recovered" : "Failed");1730 !err ? "recovered" : "Failed");
@@ -1785,6 +1792,7 @@ static void shutdown(struct pci_dev *pdev) · 61 unmodified lines
1785 int err;1792 int err;
1786 1793
1787 mlx5_core_info(dev, "Shutdown was called\n");1794 mlx5_core_info(dev, "Shutdown was called\n");
1795 set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
1788 err = mlx5_try_fast_unload(dev);1796 err = mlx5_try_fast_unload(dev);
1789 if (err)1797 if (err)
1790 mlx5_unload_one(dev);1798 mlx5_unload_one(dev);
@@ -1804,7 +1812,7 @@ static int mlx5_resume(struct pci_dev *pdev) · 13 unmodified lines
1804{1812{
1805 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);1813 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1806 1814
1807 return mlx5_load_one(dev);1815 return mlx5_load_one(dev, false);
1808}1816}
1809 1817
1810static const struct pci_device_id mlx5_core_pci_table[] = {1818static 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
1849 return -EIO;1857 return -EIO;
1850 }1858 }
1851 1859
1852 return mlx5_load_one(dev);1860 return mlx5_load_one(dev, true);
1853}1861}
1854 1862
1855static struct pci_driver mlx5_core_driver = {1863static 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
210int mlx5_register_device(struct mlx5_core_dev *dev);210int mlx5_register_device(struct mlx5_core_dev *dev);
211void mlx5_unregister_device(struct mlx5_core_dev *dev);211void mlx5_unregister_device(struct mlx5_core_dev *dev);
212struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);212struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
213struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev);
213void mlx5_dev_list_lock(void);214void mlx5_dev_list_lock(void);
214void mlx5_dev_list_unlock(void);215void mlx5_dev_list_unlock(void);
215int mlx5_dev_list_trylock(void);216int mlx5_dev_list_trylock(void);
@@ -290,7 +291,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev); · 74 unmodified lines
290int mlx5_init_one(struct mlx5_core_dev *dev);291int mlx5_init_one(struct mlx5_core_dev *dev);
291void mlx5_uninit_one(struct mlx5_core_dev *dev);292void mlx5_uninit_one(struct mlx5_core_dev *dev);
292void mlx5_unload_one(struct mlx5_core_dev *dev);293void mlx5_unload_one(struct mlx5_core_dev *dev);
293int mlx5_load_one(struct mlx5_core_dev *dev);294int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
294 295
295int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out);296int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out);
296 297
include/linux/mlx5/driver.h+4−1
@@ -84,7 +84,7 @@ enum mlx5_sqp_t { · 83 unmodified lines
84};84};
85 85
86enum {86enum {
87 MLX5_MAX_PORTS = 2,87 MLX5_MAX_PORTS = 4,
88};88};
89 89
90enum {90enum {
@@ -558,6 +558,7 @@ struct mlx5_debugfs_entries { · 467 unmodified lines
558 struct dentry *cq_debugfs;558 struct dentry *cq_debugfs;
559 struct dentry *cmdif_debugfs;559 struct dentry *cmdif_debugfs;
560 struct dentry *pages_debugfs;560 struct dentry *pages_debugfs;
561 struct dentry *lag_debugfs;
561};562};
562 563
563struct mlx5_ft_pool;564struct mlx5_ft_pool;
@@ -632,6 +633,7 @@ enum mlx5_device_state { · 68 unmodified lines
632 633
633enum mlx5_interface_state {634enum mlx5_interface_state {
634 MLX5_INTERFACE_STATE_UP = BIT(0),635 MLX5_INTERFACE_STATE_UP = BIT(0),
636 MLX5_BREAK_FW_WAIT = BIT(1),
635};637};
636 638
637enum mlx5_pci_status {639enum mlx5_pci_status {
@@ -1141,6 +1143,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, · 503 unmodified lines
1141 int num_counters,1143 int num_counters,
1142 size_t *offsets);1144 size_t *offsets);
1143struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev);1145struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev);
1146u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev);
1144struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);1147struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);
1145void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);1148void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);
1146int mlx5_dm_sw_icm_alloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type,1149int mlx5_dm_sw_icm_alloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type,