aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2014-09-11 07:11:17 -0400
committerRoland Dreier <roland@purestorage.com>2014-09-22 12:46:53 -0400
commit3e0629cb6c0518423c9e2671bbe8ec15dde5dcaf (patch)
treebed642a5d9178ccebddf180ca2d5cdd8a7c31092
parentf4fd40b26bd597e203639281859a758402550d62 (diff)
IB/mlx4: Avoid accessing netdevice when building RoCE qp1 header
The source MAC is needed in RoCE when building the QP1 header. Currently, this is obtained from the source net device. However, the net device may not yet exist, or can be destroyed in parallel to this QP1 send operation (e.g through the VPI port change flow) so accessing it may cause a kernel crash. To fix this, we maintain a source MAC cache per port for the net device in struct mlx4_ib_roce. This cached MAC is initialized to be the default MAC address obtained during HCA initialization via QUERY_PORT. This cached MAC is updated via the netdev event notifier handler. Since the cached MAC is held in an atomic64 object, we do not need locking when accessing it. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/hw/mlx4/main.c5
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c38
3 files changed, 28 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index c61bcee9ee8a..657ce0f810fd 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1643,6 +1643,8 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
1643 new_smac = mlx4_mac_to_u64(dev->dev_addr); 1643 new_smac = mlx4_mac_to_u64(dev->dev_addr);
1644 read_unlock(&dev_base_lock); 1644 read_unlock(&dev_base_lock);
1645 1645
1646 atomic64_set(&ibdev->iboe.mac[port - 1], new_smac);
1647
1646 mutex_lock(&ibdev->qp1_proxy_lock[port - 1]); 1648 mutex_lock(&ibdev->qp1_proxy_lock[port - 1]);
1647 qp = ibdev->qp1_proxy[port - 1]; 1649 qp = ibdev->qp1_proxy[port - 1];
1648 if (qp) { 1650 if (qp) {
@@ -2190,6 +2192,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
2190 goto err_steer_free_bitmap; 2192 goto err_steer_free_bitmap;
2191 } 2193 }
2192 2194
2195 for (j = 1; j <= ibdev->dev->caps.num_ports; j++)
2196 atomic64_set(&iboe->mac[j - 1], ibdev->dev->caps.def_mac[j]);
2197
2193 if (ib_register_device(&ibdev->ib_dev, NULL)) 2198 if (ib_register_device(&ibdev->ib_dev, NULL))
2194 goto err_steer_free_bitmap; 2199 goto err_steer_free_bitmap;
2195 2200
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e8cad3926bfc..6eb743f65f6f 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -451,6 +451,7 @@ struct mlx4_ib_iboe {
451 spinlock_t lock; 451 spinlock_t lock;
452 struct net_device *netdevs[MLX4_MAX_PORTS]; 452 struct net_device *netdevs[MLX4_MAX_PORTS];
453 struct net_device *masters[MLX4_MAX_PORTS]; 453 struct net_device *masters[MLX4_MAX_PORTS];
454 atomic64_t mac[MLX4_MAX_PORTS];
454 struct notifier_block nb; 455 struct notifier_block nb;
455 struct notifier_block nb_inet; 456 struct notifier_block nb_inet;
456 struct notifier_block nb_inet6; 457 struct notifier_block nb_inet6;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 67780452f0cf..25e0208588e6 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1390,18 +1390,10 @@ static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
1390static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac, 1390static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac,
1391 struct mlx4_qp_context *context) 1391 struct mlx4_qp_context *context)
1392{ 1392{
1393 struct net_device *ndev;
1394 u64 u64_mac; 1393 u64 u64_mac;
1395 int smac_index; 1394 int smac_index;
1396 1395
1397 1396 u64_mac = atomic64_read(&dev->iboe.mac[qp->port - 1]);
1398 ndev = dev->iboe.netdevs[qp->port - 1];
1399 if (ndev) {
1400 smac = ndev->dev_addr;
1401 u64_mac = mlx4_mac_to_u64(smac);
1402 } else {
1403 u64_mac = dev->dev->caps.def_mac[qp->port];
1404 }
1405 1397
1406 context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6); 1398 context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6);
1407 if (!qp->pri.smac) { 1399 if (!qp->pri.smac) {
@@ -2083,6 +2075,16 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
2083 return 0; 2075 return 0;
2084} 2076}
2085 2077
2078static void mlx4_u64_to_smac(u8 *dst_mac, u64 src_mac)
2079{
2080 int i;
2081
2082 for (i = ETH_ALEN; i; i--) {
2083 dst_mac[i - 1] = src_mac & 0xff;
2084 src_mac >>= 8;
2085 }
2086}
2087
2086static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, 2088static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
2087 void *wqe, unsigned *mlx_seg_len) 2089 void *wqe, unsigned *mlx_seg_len)
2088{ 2090{
@@ -2197,7 +2199,6 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
2197 } 2199 }
2198 2200
2199 if (is_eth) { 2201 if (is_eth) {
2200 u8 *smac;
2201 struct in6_addr in6; 2202 struct in6_addr in6;
2202 2203
2203 u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13; 2204 u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13;
@@ -2210,12 +2211,17 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
2210 memcpy(&ctrl->imm, ah->av.eth.mac + 2, 4); 2211 memcpy(&ctrl->imm, ah->av.eth.mac + 2, 4);
2211 memcpy(&in6, sgid.raw, sizeof(in6)); 2212 memcpy(&in6, sgid.raw, sizeof(in6));
2212 2213
2213 if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev)) 2214 if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
2214 smac = to_mdev(sqp->qp.ibqp.device)-> 2215 u64 mac = atomic64_read(&to_mdev(ib_dev)->iboe.mac[sqp->qp.port - 1]);
2215 iboe.netdevs[sqp->qp.port - 1]->dev_addr; 2216 u8 smac[ETH_ALEN];
2216 else /* use the src mac of the tunnel */ 2217
2217 smac = ah->av.eth.s_mac; 2218 mlx4_u64_to_smac(smac, mac);
2218 memcpy(sqp->ud_header.eth.smac_h, smac, 6); 2219 memcpy(sqp->ud_header.eth.smac_h, smac, ETH_ALEN);
2220 } else {
2221 /* use the src mac of the tunnel */
2222 memcpy(sqp->ud_header.eth.smac_h, ah->av.eth.s_mac, ETH_ALEN);
2223 }
2224
2219 if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) 2225 if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))
2220 mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); 2226 mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
2221 if (!is_vlan) { 2227 if (!is_vlan) {