diff options
author | Moni Shoua <monis@mellanox.com> | 2015-02-03 09:48:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-04 19:14:25 -0500 |
commit | c6215745b66a7fbeeda1a826f94dd864a2ccf654 (patch) | |
tree | 93990685d6fdba0784d68bf5ca0dbf523c930bb4 | |
parent | 146d6e19832a72136089afca51e5229d1fd72dcd (diff) |
IB/mlx4: Load balance ports in port aggregation mode
When the mlx4 IB (RoCE) device works in link aggregation mode, it
exposes a single port to upper layers. Therefore, applications always
set '1' in port_num attribute when modifying a QP or creating an address handle.
To make sure that a node uses all available ports the mlx4 driver will
override the port_num attribute with a round robin policy.
Signed-off-by: Moni Shoua <monis@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/infiniband/hw/mlx4/ah.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 19 |
4 files changed, 29 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c index 2d8c3397774f..f50a546224ad 100644 --- a/drivers/infiniband/hw/mlx4/ah.c +++ b/drivers/infiniband/hw/mlx4/ah.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/inet.h> | 37 | #include <linux/inet.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/mlx4/driver.h> | ||
39 | 40 | ||
40 | #include "mlx4_ib.h" | 41 | #include "mlx4_ib.h" |
41 | 42 | ||
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index ca522382dedc..2ed5b996b2f4 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -2153,6 +2153,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
2153 | MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); | 2153 | MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); |
2154 | 2154 | ||
2155 | ibdev->dev = dev; | 2155 | ibdev->dev = dev; |
2156 | ibdev->bond_next_port = 0; | ||
2156 | 2157 | ||
2157 | strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX); | 2158 | strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX); |
2158 | ibdev->ib_dev.owner = THIS_MODULE; | 2159 | ibdev->ib_dev.owner = THIS_MODULE; |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 2b49f9de2556..721540c9163d 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -534,6 +534,7 @@ struct mlx4_ib_dev { | |||
534 | struct mlx4_ib_qp *qp1_proxy[MLX4_MAX_PORTS]; | 534 | struct mlx4_ib_qp *qp1_proxy[MLX4_MAX_PORTS]; |
535 | /* lock when destroying qp1_proxy and getting netdev events */ | 535 | /* lock when destroying qp1_proxy and getting netdev events */ |
536 | struct mutex qp1_proxy_lock[MLX4_MAX_PORTS]; | 536 | struct mutex qp1_proxy_lock[MLX4_MAX_PORTS]; |
537 | u8 bond_next_port; | ||
537 | }; | 538 | }; |
538 | 539 | ||
539 | struct ib_event_work { | 540 | struct ib_event_work { |
@@ -629,6 +630,13 @@ static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah) | |||
629 | return container_of(ibah, struct mlx4_ib_ah, ibah); | 630 | return container_of(ibah, struct mlx4_ib_ah, ibah); |
630 | } | 631 | } |
631 | 632 | ||
633 | static inline u8 mlx4_ib_bond_next_port(struct mlx4_ib_dev *dev) | ||
634 | { | ||
635 | dev->bond_next_port = (dev->bond_next_port + 1) % dev->num_ports; | ||
636 | |||
637 | return dev->bond_next_port + 1; | ||
638 | } | ||
639 | |||
632 | int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev); | 640 | int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev); |
633 | void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev); | 641 | void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev); |
634 | 642 | ||
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 2f85fc762865..792f9dc86ada 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -1905,6 +1905,22 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
1905 | goto out; | 1905 | goto out; |
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT)) { | ||
1909 | if ((cur_state == IB_QPS_RESET) && (new_state == IB_QPS_INIT)) { | ||
1910 | if ((ibqp->qp_type == IB_QPT_RC) || | ||
1911 | (ibqp->qp_type == IB_QPT_UD) || | ||
1912 | (ibqp->qp_type == IB_QPT_UC) || | ||
1913 | (ibqp->qp_type == IB_QPT_RAW_PACKET) || | ||
1914 | (ibqp->qp_type == IB_QPT_XRC_INI)) { | ||
1915 | attr->port_num = mlx4_ib_bond_next_port(dev); | ||
1916 | } | ||
1917 | } else { | ||
1918 | /* no sense in changing port_num | ||
1919 | * when ports are bonded */ | ||
1920 | attr_mask &= ~IB_QP_PORT; | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1908 | if ((attr_mask & IB_QP_PORT) && | 1924 | if ((attr_mask & IB_QP_PORT) && |
1909 | (attr->port_num == 0 || attr->port_num > dev->num_ports)) { | 1925 | (attr->port_num == 0 || attr->port_num > dev->num_ports)) { |
1910 | pr_debug("qpn 0x%x: invalid port number (%d) specified " | 1926 | pr_debug("qpn 0x%x: invalid port number (%d) specified " |
@@ -1955,6 +1971,9 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
1955 | 1971 | ||
1956 | err = __mlx4_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state); | 1972 | err = __mlx4_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state); |
1957 | 1973 | ||
1974 | if (mlx4_is_bonded(dev->dev) && (attr_mask & IB_QP_PORT)) | ||
1975 | attr->port_num = 1; | ||
1976 | |||
1958 | out: | 1977 | out: |
1959 | mutex_unlock(&qp->mutex); | 1978 | mutex_unlock(&qp->mutex); |
1960 | return err; | 1979 | return err; |