summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/mlx4/ah.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2018-06-24 16:57:50 +0300
committerJason Gunthorpe <jgg@mellanox.com>2018-06-26 14:37:26 -0600
commit5e62d5ff1b9a6573d0d6b411893b1c17ccc21ce7 (patch)
tree4620564b01a73171f1473f068f288b0105e1875a /drivers/infiniband/hw/mlx4/ah.c
parentd9c44040ed05991bc43dddb7dbb043891b3bdb1f (diff)
IB/mlx4: Create slave AH's directly
Since slave GID's do not exist in the core gid table we can no longer use the core code to help do this without creating inconsistencies. Directly create the AH using mlx4 internal APIs. Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Diffstat (limited to 'drivers/infiniband/hw/mlx4/ah.c')
-rw-r--r--drivers/infiniband/hw/mlx4/ah.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 5e9b0837ef61..e9e3a6f390db 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -96,19 +96,29 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd,
memcpy(ah->av.eth.mac, ah_attr->roce.dmac, ETH_ALEN);
eth_zero_addr(ah->av.eth.s_mac);
+
+ /*
+ * If sgid_attr is NULL we are being called by mlx4_ib_create_ah_slave
+ * and we are directly creating an AV for a slave's gid_index.
+ */
gid_attr = ah_attr->grh.sgid_attr;
- if (is_vlan_dev(gid_attr->ndev))
- vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
- memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN);
+ if (gid_attr) {
+ if (is_vlan_dev(gid_attr->ndev))
+ vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
+ memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN);
+ ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ ah->av.eth.gid_index = ret;
+ } else {
+ /* mlx4_ib_create_ah_slave fills in the s_mac and the vlan */
+ ah->av.eth.gid_index = ah_attr->grh.sgid_index;
+ }
if (vlan_tag < 0x1000)
vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn |
(rdma_ah_get_port_num(ah_attr) << 24));
- ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
- if (ret < 0)
- return ERR_PTR(ret);
- ah->av.eth.gid_index = ret;
ah->av.eth.vlan = cpu_to_be16(vlan_tag);
ah->av.eth.hop_limit = grh->hop_limit;
if (rdma_ah_get_static_rate(ah_attr)) {
@@ -167,6 +177,40 @@ struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
return create_ib_ah(pd, ah_attr, ah); /* never fails */
}
+/* AH's created via this call must be free'd by mlx4_ib_destroy_ah. */
+struct ib_ah *mlx4_ib_create_ah_slave(struct ib_pd *pd,
+ struct rdma_ah_attr *ah_attr,
+ int slave_sgid_index, u8 *s_mac,
+ u16 vlan_tag)
+{
+ struct rdma_ah_attr slave_attr = *ah_attr;
+ struct mlx4_ib_ah *mah;
+ struct ib_ah *ah;
+
+ slave_attr.grh.sgid_attr = NULL;
+ slave_attr.grh.sgid_index = slave_sgid_index;
+ ah = mlx4_ib_create_ah(pd, &slave_attr, NULL);
+ if (IS_ERR(ah))
+ return ah;
+
+ ah->device = pd->device;
+ ah->pd = pd;
+ ah->type = ah_attr->type;
+ mah = to_mah(ah);
+
+ /* get rid of force-loopback bit */
+ mah->av.ib.port_pd &= cpu_to_be32(0x7FFFFFFF);
+
+ if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE)
+ memcpy(mah->av.eth.s_mac, s_mac, 6);
+
+ if (vlan_tag < 0x1000)
+ vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
+ mah->av.eth.vlan = cpu_to_be16(vlan_tag);
+
+ return ah;
+}
+
int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
{
struct mlx4_ib_ah *ah = to_mah(ibah);