aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2016-09-12 12:16:20 -0400
committerDoug Ledford <dledford@redhat.com>2016-09-16 14:14:08 -0400
commit8ec07bf8a8b57d6c58927a16a0a22c0115cf2855 (patch)
tree6ea9c5b90d4e6a6f0dcad816254fe0be6a1a8b27
parentbaa0be7026e2f7d1d40bfd45909044169e9e3c68 (diff)
IB/mlx4: Use correct subnet-prefix in QP1 mads under SR-IOV
When sending QP1 MAD packets which use a GRH, the source GID (which consists of the 64-bit subnet prefix, and the 64 bit port GUID) must be included in the packet GRH. For SR-IOV, a GID cache is used, since the source GID needs to be the slave's source GID, and not the Hypervisor's GID. This cache also included a subnet_prefix. Unfortunately, the subnet_prefix field in the cache was never initialized (to the default subnet prefix 0xfe80::0). As a result, this field remained all zeroes. Therefore, when SR-IOV was active, all QP1 packets which included a GRH had a source GID subnet prefix of all-zeroes. However, the subnet-prefix should initially be 0xfe80::0 (the default subnet prefix). In addition, if OpenSM modifies a port's subnet prefix, the new subnet prefix must be used in the GRH when sending QP1 packets. To fix this we now initialize the subnet prefix in the SR-IOV GID cache to the default subnet prefix. We update the cached value if/when OpenSM modifies the port's subnet prefix. We take this cached value when sending QP1 packets when SR-IOV is active. Note that the value is stored as an atomic64. This eliminates any need for locking when the subnet prefix is being updated. Note also that we depend on the FW generating the "port management change" event for tracking subnet-prefix changes performed by OpenSM. If running early FW (before 2.9.4630), subnet prefix changes will not be tracked (but the default subnet prefix still will be stored in the cache; therefore users who do not modify the subnet prefix will not have a problem). IF there is a need for such tracking also for early FW, we will add that capability in a subsequent patch. Fixes: 1ffeb2eb8be9 ("IB/mlx4: SR-IOV IB context objects and proxy/tunnel SQP support") Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c23
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h2
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c5
3 files changed, 27 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 9c2e53d28f98..0f21c3a25552 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -1128,6 +1128,27 @@ void handle_port_mgmt_change_event(struct work_struct *work)
1128 1128
1129 /* Generate GUID changed event */ 1129 /* Generate GUID changed event */
1130 if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) { 1130 if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) {
1131 if (mlx4_is_master(dev->dev)) {
1132 union ib_gid gid;
1133 int err = 0;
1134
1135 if (!eqe->event.port_mgmt_change.params.port_info.gid_prefix)
1136 err = __mlx4_ib_query_gid(&dev->ib_dev, port, 0, &gid, 1);
1137 else
1138 gid.global.subnet_prefix =
1139 eqe->event.port_mgmt_change.params.port_info.gid_prefix;
1140 if (err) {
1141 pr_warn("Could not change QP1 subnet prefix for port %d: query_gid error (%d)\n",
1142 port, err);
1143 } else {
1144 pr_debug("Changing QP1 subnet prefix for port %d. old=0x%llx. new=0x%llx\n",
1145 port,
1146 (u64)atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix),
1147 be64_to_cpu(gid.global.subnet_prefix));
1148 atomic64_set(&dev->sriov.demux[port - 1].subnet_prefix,
1149 be64_to_cpu(gid.global.subnet_prefix));
1150 }
1151 }
1131 mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); 1152 mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE);
1132 /*if master, notify all slaves*/ 1153 /*if master, notify all slaves*/
1133 if (mlx4_is_master(dev->dev)) 1154 if (mlx4_is_master(dev->dev))
@@ -2202,6 +2223,8 @@ int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev)
2202 if (err) 2223 if (err)
2203 goto demux_err; 2224 goto demux_err;
2204 dev->sriov.demux[i].guid_cache[0] = gid.global.interface_id; 2225 dev->sriov.demux[i].guid_cache[0] = gid.global.interface_id;
2226 atomic64_set(&dev->sriov.demux[i].subnet_prefix,
2227 be64_to_cpu(gid.global.subnet_prefix));
2205 err = alloc_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1, 2228 err = alloc_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1,
2206 &dev->sriov.sqps[i]); 2229 &dev->sriov.sqps[i]);
2207 if (err) 2230 if (err)
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 7c5832ede4bd..686ab48ff644 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -448,7 +448,7 @@ struct mlx4_ib_demux_ctx {
448 struct workqueue_struct *wq; 448 struct workqueue_struct *wq;
449 struct workqueue_struct *ud_wq; 449 struct workqueue_struct *ud_wq;
450 spinlock_t ud_lock; 450 spinlock_t ud_lock;
451 __be64 subnet_prefix; 451 atomic64_t subnet_prefix;
452 __be64 guid_cache[128]; 452 __be64 guid_cache[128];
453 struct mlx4_ib_dev *dev; 453 struct mlx4_ib_dev *dev;
454 /* the following lock protects both mcg_table and mcg_mgid0_list */ 454 /* the following lock protects both mcg_table and mcg_mgid0_list */
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index e398c04903fa..7fb9629bd12b 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -2502,8 +2502,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_ud_wr *wr,
2502 * we must use our own cache 2502 * we must use our own cache
2503 */ 2503 */
2504 sqp->ud_header.grh.source_gid.global.subnet_prefix = 2504 sqp->ud_header.grh.source_gid.global.subnet_prefix =
2505 to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. 2505 cpu_to_be64(atomic64_read(&(to_mdev(ib_dev)->sriov.
2506 subnet_prefix; 2506 demux[sqp->qp.port - 1].
2507 subnet_prefix)));
2507 sqp->ud_header.grh.source_gid.global.interface_id = 2508 sqp->ud_header.grh.source_gid.global.interface_id =
2508 to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. 2509 to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
2509 guid_cache[ah->av.ib.gid_index]; 2510 guid_cache[ah->av.ib.gid_index];