Commit b7403217 authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe

IB: Make ib_init_ah_attr_from_wc set sgid_attr

The work completion is inspected to determine what dgid table entry was
used to receieve the packet, produces a sgid_attr that matches and sticks
it in the ah_attr.

All callers of this function are now required to release the ah_attr on
success.
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 70324739
...@@ -1091,6 +1091,9 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err) ...@@ -1091,6 +1091,9 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
wait_for_completion(&cm_id_priv->comp); wait_for_completion(&cm_id_priv->comp);
while ((work = cm_dequeue_work(cm_id_priv)) != NULL) while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
cm_free_work(work); cm_free_work(work);
rdma_destroy_ah_attr(&cm_id_priv->av.ah_attr);
rdma_destroy_ah_attr(&cm_id_priv->alt_av.ah_attr);
kfree(cm_id_priv->private_data); kfree(cm_id_priv->private_data);
kfree(cm_id_priv); kfree(cm_id_priv);
} }
......
...@@ -268,6 +268,7 @@ static void recv_handler(struct ib_mad_agent *agent, ...@@ -268,6 +268,7 @@ static void recv_handler(struct ib_mad_agent *agent,
packet->mad.hdr.traffic_class = grh->traffic_class; packet->mad.hdr.traffic_class = grh->traffic_class;
memcpy(packet->mad.hdr.gid, &grh->dgid, 16); memcpy(packet->mad.hdr.gid, &grh->dgid, 16);
packet->mad.hdr.flow_label = cpu_to_be32(grh->flow_label); packet->mad.hdr.flow_label = cpu_to_be32(grh->flow_label);
rdma_destroy_ah_attr(&ah_attr);
} }
if (queue_packet(file, agent, packet)) if (queue_packet(file, agent, packet))
......
...@@ -636,16 +636,16 @@ static bool find_gid_index(const union ib_gid *gid, ...@@ -636,16 +636,16 @@ static bool find_gid_index(const union ib_gid *gid,
return true; return true;
} }
static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num, static const struct ib_gid_attr *
u16 vlan_id, const union ib_gid *sgid, get_sgid_attr_from_eth(struct ib_device *device, u8 port_num,
enum ib_gid_type gid_type, u16 vlan_id, const union ib_gid *sgid,
u16 *gid_index) enum ib_gid_type gid_type)
{ {
struct find_gid_index_context context = {.vlan_id = vlan_id, struct find_gid_index_context context = {.vlan_id = vlan_id,
.gid_type = gid_type}; .gid_type = gid_type};
return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index, return rdma_find_gid_by_filter(device, sgid, port_num, find_gid_index,
&context, gid_index); &context);
} }
int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr, int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
...@@ -689,37 +689,24 @@ EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr); ...@@ -689,37 +689,24 @@ EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
static int ib_resolve_unicast_gid_dmac(struct ib_device *device, static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
struct rdma_ah_attr *ah_attr) struct rdma_ah_attr *ah_attr)
{ {
struct ib_gid_attr sgid_attr; struct ib_global_route *grh = rdma_ah_retrieve_grh(ah_attr);
struct ib_global_route *grh; const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
int hop_limit = 0xff; int hop_limit = 0xff;
union ib_gid sgid; int ret = 0;
int ret;
grh = rdma_ah_retrieve_grh(ah_attr);
ret = ib_get_cached_gid(device, rdma_ah_get_port_num(ah_attr),
grh->sgid_index, &sgid, &sgid_attr);
if (ret || !sgid_attr.ndev) {
if (!ret)
ret = -ENXIO;
return ret;
}
/* If destination is link local and source GID is RoCEv1, /* If destination is link local and source GID is RoCEv1,
* IP stack is not used. * IP stack is not used.
*/ */
if (rdma_link_local_addr((struct in6_addr *)grh->dgid.raw) && if (rdma_link_local_addr((struct in6_addr *)grh->dgid.raw) &&
sgid_attr.gid_type == IB_GID_TYPE_ROCE) { sgid_attr->gid_type == IB_GID_TYPE_ROCE) {
rdma_get_ll_mac((struct in6_addr *)grh->dgid.raw, rdma_get_ll_mac((struct in6_addr *)grh->dgid.raw,
ah_attr->roce.dmac); ah_attr->roce.dmac);
goto done; return ret;
} }
ret = rdma_addr_find_l2_eth_by_grh(&sgid, &grh->dgid, ret = rdma_addr_find_l2_eth_by_grh(&sgid_attr->gid, &grh->dgid,
ah_attr->roce.dmac, ah_attr->roce.dmac,
sgid_attr.ndev, &hop_limit); sgid_attr->ndev, &hop_limit);
done:
dev_put(sgid_attr.ndev);
grh->hop_limit = hop_limit; grh->hop_limit = hop_limit;
return ret; return ret;
...@@ -734,16 +721,18 @@ static int ib_resolve_unicast_gid_dmac(struct ib_device *device, ...@@ -734,16 +721,18 @@ static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
* as sgid and, sgid is used as dgid because sgid contains destinations * as sgid and, sgid is used as dgid because sgid contains destinations
* GID whom to respond to. * GID whom to respond to.
* *
* On success the caller is responsible to call rdma_destroy_ah_attr on the
* attr.
*/ */
int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num, int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
const struct ib_wc *wc, const struct ib_grh *grh, const struct ib_wc *wc, const struct ib_grh *grh,
struct rdma_ah_attr *ah_attr) struct rdma_ah_attr *ah_attr)
{ {
u32 flow_class; u32 flow_class;
u16 gid_index;
int ret; int ret;
enum rdma_network_type net_type = RDMA_NETWORK_IB; enum rdma_network_type net_type = RDMA_NETWORK_IB;
enum ib_gid_type gid_type = IB_GID_TYPE_IB; enum ib_gid_type gid_type = IB_GID_TYPE_IB;
const struct ib_gid_attr *sgid_attr;
int hoplimit = 0xff; int hoplimit = 0xff;
union ib_gid dgid; union ib_gid dgid;
union ib_gid sgid; union ib_gid sgid;
...@@ -774,40 +763,49 @@ int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num, ...@@ -774,40 +763,49 @@ int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
if (!(wc->wc_flags & IB_WC_GRH)) if (!(wc->wc_flags & IB_WC_GRH))
return -EPROTOTYPE; return -EPROTOTYPE;
ret = get_sgid_index_from_eth(device, port_num, sgid_attr = get_sgid_attr_from_eth(device, port_num,
vlan_id, &dgid, vlan_id, &dgid,
gid_type, &gid_index); gid_type);
if (ret) if (IS_ERR(sgid_attr))
return ret; return PTR_ERR(sgid_attr);
flow_class = be32_to_cpu(grh->version_tclass_flow); flow_class = be32_to_cpu(grh->version_tclass_flow);
rdma_ah_set_grh(ah_attr, &sgid, rdma_move_grh_sgid_attr(ah_attr,
flow_class & 0xFFFFF, &sgid,
(u8)gid_index, hoplimit, flow_class & 0xFFFFF,
(flow_class >> 20) & 0xFF); hoplimit,
return ib_resolve_unicast_gid_dmac(device, ah_attr); (flow_class >> 20) & 0xFF,
sgid_attr);
ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
if (ret)
rdma_destroy_ah_attr(ah_attr);
return ret;
} else { } else {
rdma_ah_set_dlid(ah_attr, wc->slid); rdma_ah_set_dlid(ah_attr, wc->slid);
rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits); rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);
if (wc->wc_flags & IB_WC_GRH) { if ((wc->wc_flags & IB_WC_GRH) == 0)
if (dgid.global.interface_id != cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) { return 0;
ret = ib_find_cached_gid_by_port(device, &dgid,
IB_GID_TYPE_IB,
port_num, NULL,
&gid_index);
if (ret)
return ret;
} else {
gid_index = 0;
}
flow_class = be32_to_cpu(grh->version_tclass_flow); if (dgid.global.interface_id !=
rdma_ah_set_grh(ah_attr, &sgid, cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
sgid_attr = rdma_find_gid_by_port(
device, &dgid, IB_GID_TYPE_IB, port_num, NULL);
} else
sgid_attr = rdma_get_gid_attr(device, port_num, 0);
if (IS_ERR(sgid_attr))
return PTR_ERR(sgid_attr);
flow_class = be32_to_cpu(grh->version_tclass_flow);
rdma_move_grh_sgid_attr(ah_attr,
&sgid,
flow_class & 0xFFFFF, flow_class & 0xFFFFF,
(u8)gid_index, hoplimit, hoplimit,
(flow_class >> 20) & 0xFF); (flow_class >> 20) & 0xFF,
} sgid_attr);
return 0; return 0;
} }
} }
...@@ -860,13 +858,17 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc, ...@@ -860,13 +858,17 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
const struct ib_grh *grh, u8 port_num) const struct ib_grh *grh, u8 port_num)
{ {
struct rdma_ah_attr ah_attr; struct rdma_ah_attr ah_attr;
struct ib_ah *ah;
int ret; int ret;
ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr); ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
return rdma_create_ah(pd, &ah_attr); ah = rdma_create_ah(pd, &ah_attr);
rdma_destroy_ah_attr(&ah_attr);
return ah;
} }
EXPORT_SYMBOL(ib_create_ah_from_wc); EXPORT_SYMBOL(ib_create_ah_from_wc);
......
...@@ -3150,6 +3150,13 @@ int ib_get_rdma_header_version(const union rdma_network_hdr *hdr); ...@@ -3150,6 +3150,13 @@ int ib_get_rdma_header_version(const union rdma_network_hdr *hdr);
* ignored unless the work completion indicates that the GRH is valid. * ignored unless the work completion indicates that the GRH is valid.
* @ah_attr: Returned attributes that can be used when creating an address * @ah_attr: Returned attributes that can be used when creating an address
* handle for replying to the message. * handle for replying to the message.
* When ib_init_ah_attr_from_wc() returns success,
* (a) for IB link layer it optionally contains a reference to SGID attribute
* when GRH is present for IB link layer.
* (b) for RoCE link layer it contains a reference to SGID attribute.
* User must invoke rdma_cleanup_ah_attr_gid_attr() to release reference to SGID
* attributes which are initialized using ib_init_ah_attr_from_wc().
*
*/ */
int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num, int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
const struct ib_wc *wc, const struct ib_grh *grh, const struct ib_wc *wc, const struct ib_grh *grh,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment