mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
OFED: Various changes from Linux 4.19
Many of these changes deal with shifting from fetcing SGID attributes
via an index in drivers to including references to SGID attributes in
other structures passed to driver callbacks which can be used directly
avoiding the need for fetching attributes via lookup functions. I had
to fixup the ROCE GID management code directly as the version in
FreeBSD is very different from Linux.
I also tweaked the change from commit
475c8de7bf to use a goto to reduce diffs
with upstream to minimize conflicts when merging upstream changes.
This contains changes from the following Linux commits:
a1a4caeebac9 IB/core: Do not set the gid type when reserving default entries
1c36cf912ad1 IB/core: Store default GID property per-table instead of per-entry
1dfce2945771 IB: Replace ib_query_gid/ib_get_cached_gid with rdma_query_gid
83f6f8d29dd3 IB/core: Make rdma_find_gid_by_filter support all protocols
c3d71b69a75c IB/core: Provide rdma_ versions of the gid cache API
77e786fcbe2e IB/core: Replace ib_query_gid with rdma_get_gid_attr
bf399c2cadfa IB/core: Introduce GID attribute get, put and hold APIs
f4df9a7c34d8 RDMA: Use GID from the ib_gid_attr during the add_gid() callback
b150c3862d21 IB/core: Introduce GID entry reference counts
47ec38666210 RDMA: Convert drivers to use sgid_attr instead of sgid_index
d97099fe53ed IB{cm, core}: Introduce and use ah_attr copy, move, replace APIs
947c99ecfcb4 IB/core: Tidy ib_resolve_eth_dmac
8d9ec9addd6c IB/core: Add a sgid_attr pointer to struct rdma_ah_attr
89af969a6653 RDMA: Convert drivers to use the AH's sgid_attr in post_wr paths
1a1f460ff151 RDMA: Hold the sgid_attr inside the struct ib_ah/qp
7492052a186b IB/mlx4: Use GID attribute from ah attribute
59d40813328f IB/core: Free GID table entry during GID deletion
881456789248 RDMA/cma: Consider net namespace while leaving multicast group
4ed13a5f2d60 IB/cm: Keep track of the sgid_attr that created the cm id
aa74f4878d61 IB: Make init_ah_attr_grh_fields set sgid_attr
f685c19529f0 IB: Make ib_init_ah_from_mcmember set sgid_attr
b7403217656d IB: Make ib_init_ah_attr_from_wc set sgid_attr
ea8c2d8f6014 RDMA/core: Remove unused ib cache functions
a8872d53e9b7 IB/cm: Use sgid_attr from the AV
398391071f25 IB/cm: Replace members of sa_path_rec with 'struct sgid_attr *'
815d456ef21a IB/cm: Pass the sgid_attr through various events
4eefd62c17a9 include/rdma/opa_addr.h: Fix an endianness issue
f8c2d2280cf6 RDMA/core: Remove set-but-not-used variables
28e39894ed4f RDMA/core: Remove ib_find_cached_gid() and ib_find_cached_gid_by_port()
07e7056aff6c IB/core: Simplify check for RoCE route resolve
40ddacf2dda9 RDMA/umem: Don't hold mmap_sem for too long
1215cb7c88ec RDMA/umem: Refactor exit paths in ib_umem_get
c012691508f5 IB/cm: Remove cma_multicast->igmp_joined
4b4671a0f269 IB/IPoIB: Simplify ib_post_(send|recv|srq_recv)() calls
1fec77bf8fcd RDMA/core: Simplify ib_post_(send|recv|srq_recv)() calls
bb039a870c05 IB/core: Allow ULPs to specify NULL as the third ib_post_(send|recv|srq_recv)() argument
643d213a9a03 RDMA/cma: Do not ignore net namespace for unbound cm_id
d274e45ce1ed RDMA/cma: Consider netdevice for RoCE ports
cee104334c98 IB/core: Introduce and use sgid_attr in CM requests
7150c3d5544b RDMA/core: Remove {create,destroy}_ah from mandatory verbs
854633165164 RDMA/core: Prefix _ib to IB/RoCE specific functions
7582df826734 RDMA/core: Avoid holding lock while initializing fields on stack
79d684f02647 RDMA/core: Simplify gid type check in cma_acquire_dev()
ca3a8ace2b12 RDMA/core: Return bool instead of int
05e0b86c413d RDMA/cma: Get rid of 1 bit boolean
e7ff98aefc9e RDMA/cma: Constify path record, ib_cm_event, listen_id pointers
2df7dba855e1 RDMA/core: Constify dst_addr argument
219d2e9dfda9 RDMA/cma: Simplify rdma_resolve_addr() error flow
26e551c5aec5 RDMA: Fix return code check in rdma_set_cq_moderation
58796e67d5d5 IB/ucm: Initialize sgid request GID attribute pointer
dd81b2c8a333 IB/core: Change filter function return type from int to bool
93065ac753e4 mm, oom: distinguish blockable mode for mmu notifiers
0d23ba6034b9 RDMA/ucma: check fd type in ucma_migrate_id()
Part of cee104334c98 was previously merged into FreeBSD. Namely, SGID
index fields had been added to the two param structures instead and
roce_get_net_dev_by_cm_event was implemented using SGID indices.
Tested by: Wafa Hamzah <[email protected]> (mlx5_ib)
Tested by: John Baldwin <[email protected]> (iw_cxgbe)
Sponsored by: Chelsio Communications
This commit is contained in:
1 parent
f08a980902
commit
6a75471dbc
48 files changed
+1433
-1168
No files matched your search
@@ -509,8 +509,7 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_re_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr, void **context)
|
||||
int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
|
||||
{
|
||||
int rc;
|
||||
u32 tbl_idx = 0;
|
||||
@@ -521,11 +520,12 @@ int bnxt_re_add_gid(const union ib_gid *gid,
|
||||
if ((attr->ndev) && is_vlan_dev(attr->ndev))
|
||||
vlan_id = vlan_dev_vlan_id(attr->ndev);
|
||||
|
||||
rc = bnxt_qplib_add_sgid(sgid_tbl, gid,
|
||||
rc = bnxt_qplib_add_sgid(sgid_tbl, &attr->gid,
|
||||
rdev->dev_addr,
|
||||
vlan_id, true, &tbl_idx);
|
||||
if (rc == -EALREADY) {
|
||||
dev_dbg(rdev_to_dev(rdev), "GID %pI6 is already present\n", gid);
|
||||
dev_dbg(rdev_to_dev(rdev), "GID %pI6 is already present\n",
|
||||
&attr->gid);
|
||||
ctx_tbl = sgid_tbl->ctx;
|
||||
if (!ctx_tbl[tbl_idx]) {
|
||||
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
@@ -921,53 +921,29 @@ static u8 _to_bnxt_re_nw_type(enum rdma_network_type ntype)
|
||||
return nw_type;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bnxt_re_get_cached_gid(struct ib_device *dev, u8 port_num, int index,
|
||||
union ib_gid *sgid, struct ib_gid_attr **sgid_attr,
|
||||
const struct ib_global_route *grh, struct ib_ah *ah)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ib_get_cached_gid(dev, port_num, index, sgid, *sgid_attr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline enum rdma_network_type
|
||||
bnxt_re_gid_to_network_type(struct ib_gid_attr *sgid_attr,
|
||||
union ib_gid *sgid)
|
||||
{
|
||||
return ib_gid_to_network_type(sgid_attr->gid_type, sgid);
|
||||
}
|
||||
|
||||
static int bnxt_re_get_ah_info(struct bnxt_re_dev *rdev,
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
struct bnxt_re_ah_info *ah_info)
|
||||
{
|
||||
struct ib_gid_attr *gattr;
|
||||
const struct ib_gid_attr *gattr;
|
||||
enum rdma_network_type ib_ntype;
|
||||
u8 ntype;
|
||||
union ib_gid *gid;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
|
||||
int rc = 0;
|
||||
|
||||
gid = &ah_info->sgid;
|
||||
gattr = &ah_info->sgid_attr;
|
||||
|
||||
rc = bnxt_re_get_cached_gid(&rdev->ibdev, 1, grh->sgid_index,
|
||||
gid, &gattr, grh, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
gattr = grh->sgid_attr;
|
||||
ah_info->sgid_attr = *gattr;
|
||||
ah_info->sgid = gattr->gid;
|
||||
|
||||
/* Get vlan tag */
|
||||
if (gattr->ndev) {
|
||||
if (is_vlan_dev(gattr->ndev))
|
||||
ah_info->vlan_tag = vlan_dev_vlan_id(gattr->ndev);
|
||||
if_rele(gattr->ndev);
|
||||
}
|
||||
|
||||
/* Get network header type for this GID */
|
||||
|
||||
ib_ntype = bnxt_re_gid_to_network_type(gattr, gid);
|
||||
ib_ntype = rdma_gid_attr_network_type(gattr);
|
||||
ntype = _to_bnxt_re_nw_type(ib_ntype);
|
||||
ah_info->nw_type = ntype;
|
||||
|
||||
@@ -2584,11 +2560,10 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
||||
struct bnxt_qplib_ppp *ppp = NULL;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_re_qp *qp;
|
||||
struct ib_gid_attr *sgid_attr;
|
||||
struct ib_gid_attr gid_attr;
|
||||
union ib_gid sgid, *gid_ptr = NULL;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
const union ib_gid *gid_ptr = NULL;
|
||||
u8 nw_type;
|
||||
int rc, entries, status;
|
||||
int rc, entries;
|
||||
bool is_copy_to_udata = false;
|
||||
bool is_qpmtu_high = false;
|
||||
|
||||
@@ -2671,18 +2646,12 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
||||
qp->qplib_qp.ah.traffic_class = grh->traffic_class;
|
||||
qp->qplib_qp.ah.sl = rdma_ah_get_sl(&qp_attr->ah_attr);
|
||||
ether_addr_copy(qp->qplib_qp.ah.dmac, ROCE_DMAC(&qp_attr->ah_attr));
|
||||
sgid_attr = &gid_attr;
|
||||
status = bnxt_re_get_cached_gid(&rdev->ibdev, 1,
|
||||
grh->sgid_index,
|
||||
&sgid, &sgid_attr,
|
||||
grh, NULL);
|
||||
if (!status)
|
||||
if_rele(sgid_attr->ndev);
|
||||
gid_ptr = &sgid;
|
||||
sgid_attr = grh->sgid_attr;
|
||||
gid_ptr = &sgid_attr->gid;
|
||||
if (sgid_attr->ndev) {
|
||||
memcpy(qp->qplib_qp.smac, rdev->dev_addr,
|
||||
ETH_ALEN);
|
||||
nw_type = bnxt_re_gid_to_network_type(sgid_attr, &sgid);
|
||||
nw_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
dev_dbg(rdev_to_dev(rdev),
|
||||
"Connection using the nw_type %d\n", nw_type);
|
||||
switch (nw_type) {
|
||||
|
||||
@@ -296,8 +296,7 @@ void bnxt_re_compat_qfwstr(void);
|
||||
int bnxt_re_query_pkey(struct ib_device *ibdev, u8 port_num,
|
||||
u16 index, u16 *pkey);
|
||||
int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context);
|
||||
int bnxt_re_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr, void **context);
|
||||
int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context);
|
||||
int bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num,
|
||||
int index, union ib_gid *gid);
|
||||
enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
|
||||
|
||||
@@ -253,8 +253,7 @@ int irdma_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
|
||||
void irdma_dealloc_ucontext(struct ib_ucontext *context);
|
||||
int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
||||
void irdma_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
|
||||
int irdma_add_gid(const union ib_gid *,
|
||||
const struct ib_gid_attr *, void **);
|
||||
int irdma_add_gid(const struct ib_gid_attr *, void **);
|
||||
int irdma_del_gid(const struct ib_gid_attr *, void **);
|
||||
struct ib_device *ib_device_get_by_netdev(struct ifnet *ndev, int driver_id);
|
||||
void ib_device_put(struct ib_device *device);
|
||||
|
||||
@@ -77,8 +77,7 @@ irdma_get_dev_fw_str(struct ib_device *dev,
|
||||
}
|
||||
|
||||
int
|
||||
irdma_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
irdma_add_gid(const struct ib_gid_attr *attr,
|
||||
void **context)
|
||||
{
|
||||
return 0;
|
||||
@@ -528,8 +527,8 @@ irdma_create_sleepable_ah(struct ib_ah *ib_ah,
|
||||
struct irdma_pd *pd = to_iwpd(ib_ah->pd);
|
||||
struct irdma_ah *ah = container_of(ib_ah, struct irdma_ah, ibah);
|
||||
struct irdma_device *iwdev = to_iwdev(ib_ah->pd->device);
|
||||
union ib_gid sgid;
|
||||
struct ib_gid_attr sgid_attr;
|
||||
const union ib_gid *sgid;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
struct irdma_pci_f *rf = iwdev->rf;
|
||||
struct irdma_sc_ah *sc_ah;
|
||||
u32 ah_id = 0;
|
||||
@@ -556,24 +555,12 @@ irdma_create_sleepable_ah(struct ib_ah *ib_ah,
|
||||
irdma_sc_init_ah(&rf->sc_dev, sc_ah);
|
||||
ah->sgid_index = attr->grh.sgid_index;
|
||||
memcpy(&ah->dgid, &attr->grh.dgid, sizeof(ah->dgid));
|
||||
rcu_read_lock();
|
||||
err = ib_get_cached_gid(&iwdev->ibdev, attr->port_num,
|
||||
attr->grh.sgid_index, &sgid, &sgid_attr);
|
||||
rcu_read_unlock();
|
||||
if (err) {
|
||||
irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS,
|
||||
"GID lookup at idx=%d with port=%d failed\n",
|
||||
attr->grh.sgid_index, attr->port_num);
|
||||
err = -EINVAL;
|
||||
goto err_gid_l2;
|
||||
}
|
||||
rdma_gid2ip((struct sockaddr *)&sgid_addr, &sgid);
|
||||
sgid_attr = attr->grh.sgid_attr;
|
||||
sgid = &sgid_attr->gid;
|
||||
rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
|
||||
rdma_gid2ip((struct sockaddr *)&dgid_addr, &attr->grh.dgid);
|
||||
ah->av.attrs = *attr;
|
||||
ah->av.net_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid);
|
||||
|
||||
if (sgid_attr.ndev)
|
||||
dev_put(sgid_attr.ndev);
|
||||
ah->av.net_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
|
||||
ah_info = &sc_ah->ah_info;
|
||||
ah_info->ah_idx = ah_id;
|
||||
@@ -588,10 +575,10 @@ irdma_create_sleepable_ah(struct ib_ah *ib_ah,
|
||||
|
||||
ether_addr_copy(dmac, attr->roce.dmac);
|
||||
|
||||
irdma_fill_ah_info(if_getvnet(iwdev->netdev), ah_info, &sgid_attr, &sgid_addr, &dgid_addr,
|
||||
irdma_fill_ah_info(if_getvnet(iwdev->netdev), ah_info, sgid_attr, &sgid_addr, &dgid_addr,
|
||||
dmac, ah->av.net_type);
|
||||
|
||||
err = irdma_create_ah_vlan_tag(iwdev, pd, ah_info, &sgid_attr, dmac);
|
||||
err = irdma_create_ah_vlan_tag(iwdev, pd, ah_info, sgid_attr, dmac);
|
||||
if (err)
|
||||
goto err_gid_l2;
|
||||
|
||||
@@ -1393,27 +1380,19 @@ int
|
||||
kc_irdma_set_roce_cm_info(struct irdma_qp *iwqp, struct ib_qp_attr *attr,
|
||||
u16 *vlan_id)
|
||||
{
|
||||
int ret;
|
||||
union ib_gid sgid;
|
||||
struct ib_gid_attr sgid_attr;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
struct irdma_av *av = &iwqp->roce_ah.av;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
|
||||
|
||||
ret = ib_get_cached_gid(iwqp->ibqp.device,
|
||||
rdma_ah_get_port_num(&attr->ah_attr),
|
||||
grh->sgid_index, &sgid,
|
||||
&sgid_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
sgid_attr = grh->sgid_attr;
|
||||
|
||||
if (sgid_attr.ndev) {
|
||||
*vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
|
||||
ether_addr_copy(iwqp->ctx_info.roce_info->mac_addr, if_getlladdr(sgid_attr.ndev));
|
||||
if (sgid_attr->ndev) {
|
||||
*vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev);
|
||||
ether_addr_copy(iwqp->ctx_info.roce_info->mac_addr, if_getlladdr(sgid_attr->ndev));
|
||||
}
|
||||
|
||||
av->net_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid);
|
||||
rdma_gid2ip((struct sockaddr *)&av->sgid_addr, &sgid);
|
||||
dev_put(sgid_attr.ndev);
|
||||
av->net_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
rdma_gid2ip((struct sockaddr *)&av->sgid_addr, &sgid_attr->gid);
|
||||
iwqp->sc_qp.user_pri = iwqp->ctx_info.user_pri;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -882,7 +882,7 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
|
||||
int mr_access_flags, struct ib_pd *pd,
|
||||
struct ib_udata *udata);
|
||||
int mlx4_ib_gid_index_to_real_index(struct mlx4_ib_dev *ibdev,
|
||||
u8 port_num, int index);
|
||||
const struct ib_gid_attr *attr);
|
||||
|
||||
void mlx4_sched_ib_sl2vl_update_work(struct mlx4_ib_dev *ibdev,
|
||||
int port);
|
||||
|
||||
@@ -79,14 +79,13 @@ static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
struct ib_pd *pd = ib_ah->pd;
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(ib_ah->device);
|
||||
const struct ib_gid_attr *gid_attr;
|
||||
struct mlx4_ib_ah *ah = to_mah(ib_ah);
|
||||
struct mlx4_dev *dev = ibdev->dev;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
|
||||
int is_mcast = 0;
|
||||
struct in6_addr in6;
|
||||
u16 vlan_tag = 0xffff;
|
||||
union ib_gid sgid;
|
||||
struct ib_gid_attr gid_attr;
|
||||
int ret;
|
||||
|
||||
memcpy(&in6, grh->dgid.raw, sizeof(in6));
|
||||
@@ -94,22 +93,16 @@ static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
|
||||
is_mcast = 1;
|
||||
|
||||
memcpy(ah->av.eth.mac, ah_attr->roce.dmac, ETH_ALEN);
|
||||
ret = ib_get_cached_gid(pd->device, rdma_ah_get_port_num(ah_attr),
|
||||
grh->sgid_index, &sgid, &gid_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
eth_zero_addr(ah->av.eth.s_mac);
|
||||
if (gid_attr.ndev) {
|
||||
vlan_tag = rdma_vlan_dev_vlan_id(gid_attr.ndev);
|
||||
memcpy(ah->av.eth.s_mac, if_getlladdr(gid_attr.ndev), ETH_ALEN);
|
||||
if_rele(gid_attr.ndev);
|
||||
}
|
||||
gid_attr = ah_attr->grh.sgid_attr;
|
||||
vlan_tag = rdma_vlan_dev_vlan_id(gid_attr->ndev);
|
||||
memcpy(ah->av.eth.s_mac, if_getlladdr(gid_attr->ndev), ETH_ALEN);
|
||||
|
||||
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,
|
||||
rdma_ah_get_port_num(ah_attr), grh->sgid_index);
|
||||
ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ah->av.eth.gid_index = ret;
|
||||
|
||||
@@ -252,9 +252,7 @@ static int mlx4_ib_update_gids(struct gid_entry *gids,
|
||||
return mlx4_ib_update_gids_v1(gids, ibdev, port_num);
|
||||
}
|
||||
|
||||
static int mlx4_ib_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
void **context)
|
||||
static int mlx4_ib_add_gid(const struct ib_gid_attr *attr, void **context)
|
||||
{
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(attr->device);
|
||||
struct mlx4_ib_iboe *iboe = &ibdev->iboe;
|
||||
@@ -277,7 +275,8 @@ static int mlx4_ib_add_gid(const union ib_gid *gid,
|
||||
port_gid_table = &iboe->gids[attr->port_num - 1];
|
||||
spin_lock_bh(&iboe->lock);
|
||||
for (i = 0; i < MLX4_MAX_PORT_GIDS; ++i) {
|
||||
if (!memcmp(&port_gid_table->gids[i].gid, gid, sizeof(*gid)) &&
|
||||
if (!memcmp(&port_gid_table->gids[i].gid,
|
||||
&attr->gid, sizeof(attr->gid)) &&
|
||||
(port_gid_table->gids[i].gid_type == attr->gid_type)) {
|
||||
found = i;
|
||||
break;
|
||||
@@ -295,7 +294,8 @@ static int mlx4_ib_add_gid(const union ib_gid *gid,
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
*context = port_gid_table->gids[free].ctx;
|
||||
memcpy(&port_gid_table->gids[free].gid, gid, sizeof(*gid));
|
||||
memcpy(&port_gid_table->gids[free].gid,
|
||||
&attr->gid, sizeof(attr->gid));
|
||||
port_gid_table->gids[free].gid_type = attr->gid_type;
|
||||
port_gid_table->gids[free].ctx->real_index = free;
|
||||
port_gid_table->gids[free].ctx->refcount = 1;
|
||||
@@ -386,17 +386,15 @@ static int mlx4_ib_del_gid(const struct ib_gid_attr *attr, void **context)
|
||||
}
|
||||
|
||||
int mlx4_ib_gid_index_to_real_index(struct mlx4_ib_dev *ibdev,
|
||||
u8 port_num, int index)
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
struct mlx4_ib_iboe *iboe = &ibdev->iboe;
|
||||
struct gid_cache_context *ctx = NULL;
|
||||
union ib_gid gid;
|
||||
struct mlx4_port_gid_table *port_gid_table;
|
||||
int real_index = -EINVAL;
|
||||
int i;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
struct ib_gid_attr attr;
|
||||
u8 port_num = attr->port_num;
|
||||
|
||||
if (port_num > MLX4_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
@@ -405,21 +403,15 @@ int mlx4_ib_gid_index_to_real_index(struct mlx4_ib_dev *ibdev,
|
||||
port_num = 1;
|
||||
|
||||
if (!rdma_cap_roce_gid_table(&ibdev->ib_dev, port_num))
|
||||
return index;
|
||||
|
||||
ret = ib_get_cached_gid(&ibdev->ib_dev, port_num, index, &gid, &attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (attr.ndev)
|
||||
if_rele(attr.ndev);
|
||||
return attr->index;
|
||||
|
||||
spin_lock_irqsave(&iboe->lock, flags);
|
||||
port_gid_table = &iboe->gids[port_num - 1];
|
||||
|
||||
for (i = 0; i < MLX4_MAX_PORT_GIDS; ++i)
|
||||
if (!memcmp(&port_gid_table->gids[i].gid, &gid, sizeof(gid)) &&
|
||||
attr.gid_type == port_gid_table->gids[i].gid_type) {
|
||||
if (!memcmp(&port_gid_table->gids[i].gid,
|
||||
&attr->gid, sizeof(attr->gid)) &&
|
||||
attr->gid_type == port_gid_table->gids[i].gid_type) {
|
||||
ctx = port_gid_table->gids[i].ctx;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1412,9 +1412,8 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct rdma_ah_attr *ah
|
||||
|
||||
if (rdma_ah_get_ah_flags(ah) & IB_AH_GRH) {
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(ah);
|
||||
int real_sgid_index = mlx4_ib_gid_index_to_real_index(dev,
|
||||
port,
|
||||
grh->sgid_index);
|
||||
int real_sgid_index =
|
||||
mlx4_ib_gid_index_to_real_index(dev, grh->sgid_attr);
|
||||
|
||||
if (real_sgid_index < 0)
|
||||
return real_sgid_index;
|
||||
@@ -1627,6 +1626,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
enum ib_qp_state new_state,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
const struct ib_gid_attr *gid_attr = NULL;
|
||||
struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
|
||||
struct mlx4_ib_qp *qp = to_mqp(ibqp);
|
||||
struct mlx4_ib_pd *pd;
|
||||
@@ -1773,28 +1773,16 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
if (attr_mask & IB_QP_AV) {
|
||||
u8 port_num = mlx4_is_bonded(to_mdev(ibqp->device)->dev) ? 1 :
|
||||
attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
|
||||
union ib_gid gid;
|
||||
struct ib_gid_attr gid_attr;
|
||||
u16 vlan = 0xffff;
|
||||
u8 smac[ETH_ALEN];
|
||||
int status = 0;
|
||||
int is_eth = rdma_cap_eth_ah(&dev->ib_dev, port_num) &&
|
||||
rdma_ah_get_ah_flags(&attr->ah_attr) & IB_AH_GRH;
|
||||
|
||||
if (is_eth) {
|
||||
int index =
|
||||
rdma_ah_read_grh(&attr->ah_attr)->sgid_index;
|
||||
|
||||
status = ib_get_cached_gid(ibqp->device, port_num,
|
||||
index, &gid, &gid_attr);
|
||||
if (!status && gid_attr.ndev) {
|
||||
vlan = rdma_vlan_dev_vlan_id(gid_attr.ndev);
|
||||
memcpy(smac, if_getlladdr(gid_attr.ndev), ETH_ALEN);
|
||||
if_rele(gid_attr.ndev);
|
||||
}
|
||||
gid_attr = attr->ah_attr.grh.sgid_attr;
|
||||
vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev);
|
||||
memcpy(smac, if_getlladdr(gid_attr->ndev), ETH_ALEN);
|
||||
}
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
|
||||
port_num, vlan, smac))
|
||||
@@ -1805,7 +1793,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
|
||||
if (is_eth &&
|
||||
(cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR)) {
|
||||
u8 qpc_roce_mode = gid_type_to_qpc(gid_attr.gid_type);
|
||||
u8 qpc_roce_mode = gid_type_to_qpc(gid_attr->gid_type);
|
||||
|
||||
if (qpc_roce_mode == MLX4_QPC_ROCE_MODE_UNDEFINED) {
|
||||
err = -EINVAL;
|
||||
@@ -2538,10 +2526,8 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, const struct ib_ud_wr *wr,
|
||||
to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
|
||||
guid_cache[ah->av.ib.gid_index];
|
||||
} else {
|
||||
ib_get_cached_gid(ib_dev,
|
||||
be32_to_cpu(ah->av.ib.port_pd) >> 24,
|
||||
ah->av.ib.gid_index,
|
||||
&sqp->ud_header.grh.source_gid, NULL);
|
||||
sqp->ud_header.grh.source_gid =
|
||||
ah->ibah.sgid_attr->gid;
|
||||
}
|
||||
}
|
||||
memcpy(sqp->ud_header.grh.destination_gid.raw,
|
||||
|
||||
@@ -1050,10 +1050,8 @@ int mlx5_ib_get_vf_stats(struct ib_device *device, int vf,
|
||||
int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port,
|
||||
u64 guid, int type);
|
||||
|
||||
__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
int index);
|
||||
int mlx5_get_roce_gid_type(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
int index, enum ib_gid_type *gid_type);
|
||||
__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev,
|
||||
const struct ib_gid_attr *attr);
|
||||
|
||||
/* GSI QP helper functions */
|
||||
struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
|
||||
|
||||
@@ -49,9 +49,7 @@ static void create_ib_ah(struct mlx5_ib_dev *dev,
|
||||
memcpy(ah->av.rmac, ah_attr->roce.dmac,
|
||||
sizeof(ah_attr->roce.dmac));
|
||||
ah->av.udp_sport =
|
||||
mlx5_get_roce_udp_sport(dev,
|
||||
rdma_ah_get_port_num(ah_attr),
|
||||
rdma_ah_read_grh(ah_attr)->sgid_index);
|
||||
mlx5_get_roce_udp_sport(dev, ah_attr->grh.sgid_attr);
|
||||
ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0x7) << 1;
|
||||
} else {
|
||||
ah->av.rlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr));
|
||||
|
||||
@@ -1099,7 +1099,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
|
||||
int err;
|
||||
|
||||
if (!MLX5_CAP_GEN(dev->mdev, cq_moderation))
|
||||
return -ENOSYS;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = mlx5_core_modify_cq_moderation(dev->mdev, &mcq->mcq,
|
||||
cq_period, cq_count);
|
||||
|
||||
@@ -428,12 +428,11 @@ static int set_roce_addr(struct ib_device *device, u8 port_num,
|
||||
return mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
|
||||
static int mlx5_ib_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
static int mlx5_ib_add_gid(const struct ib_gid_attr *attr,
|
||||
__always_unused void **context)
|
||||
{
|
||||
return set_roce_addr(attr->device, attr->port_num, attr->index, gid,
|
||||
attr);
|
||||
return set_roce_addr(attr->device, attr->port_num, attr->index,
|
||||
&attr->gid, attr);
|
||||
}
|
||||
|
||||
static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
|
||||
@@ -443,47 +442,15 @@ static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
|
||||
NULL);
|
||||
}
|
||||
|
||||
__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
int index)
|
||||
__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev,
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
struct ib_gid_attr attr;
|
||||
union ib_gid gid;
|
||||
|
||||
if (ib_get_cached_gid(&dev->ib_dev, port_num, index, &gid, &attr))
|
||||
return 0;
|
||||
|
||||
if (!attr.ndev)
|
||||
return 0;
|
||||
|
||||
if_rele(attr.ndev);
|
||||
|
||||
if (attr.gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
|
||||
if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
|
||||
return 0;
|
||||
|
||||
return cpu_to_be16(MLX5_CAP_ROCE(dev->mdev, r_roce_min_src_udp_port));
|
||||
}
|
||||
|
||||
int mlx5_get_roce_gid_type(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
int index, enum ib_gid_type *gid_type)
|
||||
{
|
||||
struct ib_gid_attr attr;
|
||||
union ib_gid gid;
|
||||
int ret;
|
||||
|
||||
ret = ib_get_cached_gid(&dev->ib_dev, port_num, index, &gid, &attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!attr.ndev)
|
||||
return -ENODEV;
|
||||
|
||||
if_rele(attr.ndev);
|
||||
|
||||
*gid_type = attr.gid_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB)
|
||||
|
||||
@@ -2350,14 +2350,12 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
|
||||
if (ah->type == RDMA_AH_ATTR_TYPE_ROCE) {
|
||||
if (!(ah_flags & IB_AH_GRH))
|
||||
return -EINVAL;
|
||||
err = mlx5_get_roce_gid_type(dev, port, grh->sgid_index,
|
||||
&gid_type);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(path->rmac, ah->roce.dmac, sizeof(ah->roce.dmac));
|
||||
path->udp_sport = mlx5_get_roce_udp_sport(dev, port,
|
||||
grh->sgid_index);
|
||||
path->udp_sport =
|
||||
mlx5_get_roce_udp_sport(dev, ah->grh.sgid_attr);
|
||||
path->dci_cfi_prio_sl = (sl & 0x7) << 4;
|
||||
gid_type = ah->grh.sgid_attr->gid_type;
|
||||
if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
|
||||
path->ecn_dscp = (grh->traffic_class >> 2) & 0x3f;
|
||||
} else {
|
||||
|
||||
@@ -283,10 +283,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
|
||||
header->grh.flow_label =
|
||||
ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
|
||||
header->grh.hop_limit = ah->av->hop_limit;
|
||||
ib_get_cached_gid(&dev->ib_dev,
|
||||
be32_to_cpu(ah->av->port_pd) >> 24,
|
||||
ah->av->gid_index % dev->limits.gid_table_len,
|
||||
&header->grh.source_gid, NULL);
|
||||
header->grh.source_gid = ah->ibah.sgid_attr->gid;
|
||||
memcpy(header->grh.destination_gid.raw,
|
||||
ah->av->dgid, 16);
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ qlnxr_gsi_build_header(struct qlnxr_dev *dev,
|
||||
bool has_vlan = false, has_grh_ipv6 = true;
|
||||
struct rdma_ah_attr *ah_attr = &get_qlnxr_ah((ud_wr(swr)->ah))->attr;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
|
||||
union ib_gid sgid;
|
||||
const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
|
||||
int send_size = 0;
|
||||
u16 vlan_id = 0;
|
||||
u16 ether_type;
|
||||
@@ -505,10 +505,6 @@ qlnxr_gsi_build_header(struct qlnxr_dev *dev,
|
||||
has_vlan = qlnxr_get_vlan_id_gsi(ah_attr, &vlan_id);
|
||||
ether_type = ETH_P_ROCE;
|
||||
*roce_mode = ROCE_V1;
|
||||
if (grh->sgid_index < QLNXR_MAX_SGID)
|
||||
sgid = dev->sgid_tbl[grh->sgid_index];
|
||||
else
|
||||
sgid = dev->sgid_tbl[0];
|
||||
|
||||
rc = ib_ud_header_init(send_size, false /* LRH */, true /* ETH */,
|
||||
has_vlan, has_grh_ipv6, ip_ver, has_udp,
|
||||
@@ -550,7 +546,7 @@ qlnxr_gsi_build_header(struct qlnxr_dev *dev,
|
||||
udh->grh.flow_label = grh->flow_label;
|
||||
udh->grh.hop_limit = grh->hop_limit;
|
||||
udh->grh.destination_gid = grh->dgid;
|
||||
memcpy(&udh->grh.source_gid.raw, &sgid.raw,
|
||||
memcpy(&udh->grh.source_gid.raw, sgid_attr->gid.raw,
|
||||
sizeof(udh->grh.source_gid.raw));
|
||||
QL_DPRINT12(dev->ha, "header: tc: %x, flow_label : %x, "
|
||||
"hop_limit: %x \n", udh->grh.traffic_class,
|
||||
@@ -574,7 +570,7 @@ qlnxr_gsi_build_header(struct qlnxr_dev *dev,
|
||||
udh->ip4.frag_off = htons(IP_DF);
|
||||
udh->ip4.ttl = grh->hop_limit;
|
||||
|
||||
ipv4_addr = qedr_get_ipv4_from_gid(sgid.raw);
|
||||
ipv4_addr = qedr_get_ipv4_from_gid(sgid_attr->gid.raw);
|
||||
udh->ip4.saddr = ipv4_addr;
|
||||
ipv4_addr = qedr_get_ipv4_from_gid(grh->dgid.raw);
|
||||
udh->ip4.daddr = ipv4_addr;
|
||||
|
||||
@@ -5499,7 +5499,7 @@ qlnxr_create_ah(struct ib_ah *ibah,
|
||||
|
||||
QL_DPRINT12(ha, "in create_ah\n");
|
||||
|
||||
ah->attr = *attr;
|
||||
rdma_copy_ah_attr(&ah->attr, attr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -5507,6 +5507,9 @@ qlnxr_create_ah(struct ib_ah *ibah,
|
||||
void
|
||||
qlnxr_destroy_ah(struct ib_ah *ibah, u32 flags)
|
||||
{
|
||||
struct qlnxr_ah *ah = get_qlnxr_ah(ibah);
|
||||
|
||||
rdma_destroy_ah_attr(&ah->attr);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -86,8 +86,8 @@ void ib_cache_cleanup(void);
|
||||
typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port,
|
||||
if_t idev, void *cookie);
|
||||
|
||||
typedef int (*roce_netdev_filter)(struct ib_device *device, u8 port,
|
||||
if_t idev, void *cookie);
|
||||
typedef bool (*roce_netdev_filter)(struct ib_device *device, u8 port,
|
||||
if_t idev, void *cookie);
|
||||
|
||||
void ib_enum_roce_netdev(struct ib_device *ib_dev,
|
||||
roce_netdev_filter filter,
|
||||
|
||||
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(lock);
|
||||
static LIST_HEAD(req_list);
|
||||
static struct workqueue_struct *addr_wq;
|
||||
|
||||
int rdma_addr_size(struct sockaddr *addr)
|
||||
int rdma_addr_size(const struct sockaddr *addr)
|
||||
{
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
@@ -716,7 +716,7 @@ static void process_one_req(struct work_struct *_work)
|
||||
spin_unlock_bh(&lock);
|
||||
}
|
||||
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr, int timeout_ms,
|
||||
void (*callback)(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *addr, void *context),
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -480,7 +480,7 @@ static int cm_init_av_for_lap(struct cm_port *port, struct ib_wc *wc,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
|
||||
rdma_move_ah_attr(&av->ah_attr, &new_ah_attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -514,39 +514,58 @@ static int add_cm_id_to_port_list(struct cm_id_private *cm_id_priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cm_port *get_cm_port_from_path(struct sa_path_rec *path)
|
||||
static struct cm_port *
|
||||
get_cm_port_from_path(struct sa_path_rec *path, const struct ib_gid_attr *attr)
|
||||
{
|
||||
struct cm_device *cm_dev;
|
||||
struct cm_port *port = NULL;
|
||||
unsigned long flags;
|
||||
u8 p;
|
||||
if_t ndev = ib_get_ndev_from_path(path);
|
||||
|
||||
read_lock_irqsave(&cm.device_lock, flags);
|
||||
list_for_each_entry(cm_dev, &cm.device_list, list) {
|
||||
if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
|
||||
sa_conv_pathrec_to_gid_type(path),
|
||||
ndev, &p, NULL)) {
|
||||
port = cm_dev->port[p - 1];
|
||||
break;
|
||||
if (attr) {
|
||||
read_lock_irqsave(&cm.device_lock, flags);
|
||||
list_for_each_entry(cm_dev, &cm.device_list, list) {
|
||||
if (cm_dev->ib_device == attr->device) {
|
||||
port = cm_dev->port[attr->port_num - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock_irqrestore(&cm.device_lock, flags);
|
||||
} else {
|
||||
/* SGID attribute can be NULL in following
|
||||
* conditions.
|
||||
* (a) Alternative path
|
||||
* (b) IB link layer without GRH
|
||||
* (c) LAP send messages
|
||||
*/
|
||||
read_lock_irqsave(&cm.device_lock, flags);
|
||||
list_for_each_entry(cm_dev, &cm.device_list, list) {
|
||||
attr = rdma_find_gid(cm_dev->ib_device,
|
||||
&path->sgid,
|
||||
sa_conv_pathrec_to_gid_type(path),
|
||||
NULL);
|
||||
if (!IS_ERR(attr)) {
|
||||
port = cm_dev->port[attr->port_num - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock_irqrestore(&cm.device_lock, flags);
|
||||
if (port)
|
||||
rdma_put_gid_attr(attr);
|
||||
}
|
||||
read_unlock_irqrestore(&cm.device_lock, flags);
|
||||
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
return port;
|
||||
}
|
||||
|
||||
static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
struct cm_id_private *cm_id_priv)
|
||||
static int cm_init_av_by_path(struct sa_path_rec *path,
|
||||
const struct ib_gid_attr *sgid_attr,
|
||||
struct cm_av *av,
|
||||
struct cm_id_private *cm_id_priv)
|
||||
{
|
||||
struct rdma_ah_attr new_ah_attr;
|
||||
struct cm_device *cm_dev;
|
||||
struct cm_port *port;
|
||||
int ret;
|
||||
|
||||
port = get_cm_port_from_path(path);
|
||||
port = get_cm_port_from_path(path, sgid_attr);
|
||||
if (!port)
|
||||
return -EINVAL;
|
||||
cm_dev = port->cm_dev;
|
||||
@@ -560,22 +579,26 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
|
||||
/*
|
||||
* av->ah_attr might be initialized based on wc or during
|
||||
* request processing time. So initialize a new ah_attr on stack.
|
||||
* request processing time which might have reference to sgid_attr.
|
||||
* So initialize a new ah_attr on stack.
|
||||
* If initialization fails, old ah_attr is used for sending any
|
||||
* responses. If initialization is successful, than new ah_attr
|
||||
* is used by overwriting the old one.
|
||||
* is used by overwriting the old one. So that right ah_attr
|
||||
* can be used to return an error response.
|
||||
*/
|
||||
ret = ib_init_ah_attr_from_path(cm_dev->ib_device, port->port_num, path,
|
||||
&new_ah_attr);
|
||||
&new_ah_attr, sgid_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
av->timeout = path->packet_life_time + 1;
|
||||
|
||||
ret = add_cm_id_to_port_list(cm_id_priv, av, port);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
rdma_destroy_ah_attr(&new_ah_attr);
|
||||
return ret;
|
||||
memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
|
||||
}
|
||||
rdma_move_ah_attr(&av->ah_attr, &new_ah_attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1097,6 +1120,9 @@ retest:
|
||||
wait_for_completion(&cm_id_priv->comp);
|
||||
while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
|
||||
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);
|
||||
}
|
||||
@@ -1418,12 +1444,13 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av,
|
||||
ret = cm_init_av_by_path(param->primary_path,
|
||||
param->ppath_sgid_attr, &cm_id_priv->av,
|
||||
cm_id_priv);
|
||||
if (ret)
|
||||
goto error1;
|
||||
if (param->alternate_path) {
|
||||
ret = cm_init_av_by_path(param->alternate_path,
|
||||
ret = cm_init_av_by_path(param->alternate_path, NULL,
|
||||
&cm_id_priv->alt_av, cm_id_priv);
|
||||
if (ret)
|
||||
goto error1;
|
||||
@@ -1639,15 +1666,13 @@ static void cm_opa_to_ib_sgid(struct cm_work *work,
|
||||
struct sa_path_rec *path)
|
||||
{
|
||||
struct ib_device *dev = work->port->cm_dev->ib_device;
|
||||
struct ib_gid_attr gid_attr;
|
||||
u8 port_num = work->port->port_num;
|
||||
|
||||
if (rdma_cap_opa_ah(dev, port_num) &&
|
||||
(ib_is_opa_gid(&path->sgid))) {
|
||||
union ib_gid sgid;
|
||||
|
||||
if (ib_get_cached_gid(dev, port_num, 0,
|
||||
&sgid, &gid_attr)) {
|
||||
if (rdma_query_gid(dev, port_num, 0, &sgid)) {
|
||||
dev_warn(&dev->dev,
|
||||
"Error updating sgid in CM request\n");
|
||||
return;
|
||||
@@ -1692,7 +1717,7 @@ static void cm_format_req_event(struct cm_work *work,
|
||||
param->retry_count = cm_req_get_retry_count(req_msg);
|
||||
param->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
|
||||
param->srq = cm_req_get_srq(req_msg);
|
||||
param->ppath_sgid_index = cm_id_priv->av.ah_attr.grh.sgid_index;
|
||||
param->ppath_sgid_attr = cm_id_priv->av.ah_attr.grh.sgid_attr;
|
||||
work->cm_event.private_data = &req_msg->private_data;
|
||||
}
|
||||
|
||||
@@ -1914,9 +1939,8 @@ static int cm_req_handler(struct cm_work *work)
|
||||
struct ib_cm_id *cm_id;
|
||||
struct cm_id_private *cm_id_priv, *listen_cm_id_priv;
|
||||
struct cm_req_msg *req_msg;
|
||||
union ib_gid gid;
|
||||
struct ib_gid_attr gid_attr;
|
||||
const struct ib_global_route *grh;
|
||||
const struct ib_gid_attr *gid_attr;
|
||||
int ret;
|
||||
|
||||
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
|
||||
@@ -1959,24 +1983,13 @@ static int cm_req_handler(struct cm_work *work)
|
||||
if (cm_req_has_alt_path(req_msg))
|
||||
memset(&work->path[1], 0, sizeof(work->path[1]));
|
||||
grh = rdma_ah_read_grh(&cm_id_priv->av.ah_attr);
|
||||
ret = ib_get_cached_gid(work->port->cm_dev->ib_device,
|
||||
work->port->port_num,
|
||||
grh->sgid_index,
|
||||
&gid, &gid_attr);
|
||||
if (ret) {
|
||||
ib_send_cm_rej(cm_id, IB_CM_REJ_UNSUPPORTED, NULL, 0, NULL, 0);
|
||||
goto rejected;
|
||||
}
|
||||
gid_attr = grh->sgid_attr;
|
||||
|
||||
if (gid_attr.ndev) {
|
||||
if (gid_attr && gid_attr->ndev) {
|
||||
work->path[0].rec_type =
|
||||
sa_conv_gid_to_pathrec_type(gid_attr.gid_type);
|
||||
sa_path_set_ifindex(&work->path[0],
|
||||
if_getindex(gid_attr.ndev));
|
||||
sa_path_set_ndev(&work->path[0],
|
||||
dev_net(gid_attr.ndev));
|
||||
dev_put(gid_attr.ndev);
|
||||
sa_conv_gid_to_pathrec_type(gid_attr->gid_type);
|
||||
} else {
|
||||
/* If no GID attribute or ndev is null, it is not RoCE. */
|
||||
cm_path_set_rec_type(work->port->cm_dev->ib_device,
|
||||
work->port->port_num,
|
||||
&work->path[0],
|
||||
@@ -1990,15 +2003,14 @@ static int cm_req_handler(struct cm_work *work)
|
||||
sa_path_set_dmac(&work->path[0],
|
||||
cm_id_priv->av.ah_attr.roce.dmac);
|
||||
work->path[0].hop_limit = grh->hop_limit;
|
||||
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av,
|
||||
ret = cm_init_av_by_path(&work->path[0], gid_attr, &cm_id_priv->av,
|
||||
cm_id_priv);
|
||||
if (ret) {
|
||||
int err;
|
||||
|
||||
err = ib_get_cached_gid(work->port->cm_dev->ib_device,
|
||||
work->port->port_num, 0,
|
||||
&work->path[0].sgid,
|
||||
NULL);
|
||||
err = rdma_query_gid(work->port->cm_dev->ib_device,
|
||||
work->port->port_num, 0,
|
||||
&work->path[0].sgid);
|
||||
if (err)
|
||||
ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
|
||||
NULL, 0, NULL, 0);
|
||||
@@ -2010,8 +2022,8 @@ static int cm_req_handler(struct cm_work *work)
|
||||
goto rejected;
|
||||
}
|
||||
if (cm_req_has_alt_path(req_msg)) {
|
||||
ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av,
|
||||
cm_id_priv);
|
||||
ret = cm_init_av_by_path(&work->path[1], NULL,
|
||||
&cm_id_priv->alt_av, cm_id_priv);
|
||||
if (ret) {
|
||||
ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_ALT_GID,
|
||||
&work->path[0].sgid,
|
||||
@@ -3096,7 +3108,7 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av,
|
||||
ret = cm_init_av_by_path(alternate_path, NULL, &cm_id_priv->alt_av,
|
||||
cm_id_priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -3239,8 +3251,8 @@ static int cm_lap_handler(struct cm_work *work)
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av,
|
||||
cm_id_priv);
|
||||
ret = cm_init_av_by_path(param->alternate_path, NULL,
|
||||
&cm_id_priv->alt_av, cm_id_priv);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
@@ -3444,7 +3456,9 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
|
||||
return -EINVAL;
|
||||
|
||||
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
|
||||
ret = cm_init_av_by_path(param->path, &cm_id_priv->av, cm_id_priv);
|
||||
ret = cm_init_av_by_path(param->path, param->sgid_attr,
|
||||
&cm_id_priv->av,
|
||||
cm_id_priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -3495,7 +3509,7 @@ static void cm_format_sidr_req_event(struct cm_work *work,
|
||||
param->service_id = sidr_req_msg->service_id;
|
||||
param->bth_pkey = cm_get_bth_pkey(work);
|
||||
param->port = work->port->port_num;
|
||||
param->sgid_index = rx_cm_id->av.ah_attr.grh.sgid_index;
|
||||
param->sgid_attr = rx_cm_id->av.ah_attr.grh.sgid_attr;
|
||||
work->cm_event.private_data = &sidr_req_msg->private_data;
|
||||
}
|
||||
|
||||
@@ -3629,7 +3643,8 @@ error: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_send_cm_sidr_rep);
|
||||
|
||||
static void cm_format_sidr_rep_event(struct cm_work *work)
|
||||
static void cm_format_sidr_rep_event(struct cm_work *work,
|
||||
const struct cm_id_private *cm_id_priv)
|
||||
{
|
||||
struct cm_sidr_rep_msg *sidr_rep_msg;
|
||||
struct ib_cm_sidr_rep_event_param *param;
|
||||
@@ -3642,6 +3657,7 @@ static void cm_format_sidr_rep_event(struct cm_work *work)
|
||||
param->qpn = be32_to_cpu(cm_sidr_rep_get_qpn(sidr_rep_msg));
|
||||
param->info = &sidr_rep_msg->info;
|
||||
param->info_len = sidr_rep_msg->info_length;
|
||||
param->sgid_attr = cm_id_priv->av.ah_attr.grh.sgid_attr;
|
||||
work->cm_event.private_data = &sidr_rep_msg->private_data;
|
||||
}
|
||||
|
||||
@@ -3665,7 +3681,7 @@ static int cm_sidr_rep_handler(struct cm_work *work)
|
||||
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
|
||||
spin_unlock_irq(&cm_id_priv->lock);
|
||||
|
||||
cm_format_sidr_rep_event(work);
|
||||
cm_format_sidr_rep_event(work, cm_id_priv);
|
||||
cm_process_work(cm_id_priv, work);
|
||||
return 0;
|
||||
out:
|
||||
|
||||
@@ -157,7 +157,7 @@ const void *rdma_consumer_reject_data(struct rdma_cm_id *id,
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_consumer_reject_data);
|
||||
|
||||
static int cma_check_linklocal(struct rdma_dev_addr *, struct sockaddr *);
|
||||
static int cma_check_linklocal(struct rdma_dev_addr *, const struct sockaddr *);
|
||||
static void cma_add_one(struct ib_device *device);
|
||||
static void cma_remove_one(struct ib_device *device, void *client_data);
|
||||
static enum rdma_port_space rdma_ps_from_service_id(__be64 service_id);
|
||||
@@ -360,7 +360,6 @@ struct cma_multicast {
|
||||
void *context;
|
||||
struct sockaddr_storage addr;
|
||||
struct kref mcref;
|
||||
bool igmp_joined;
|
||||
u8 join_state;
|
||||
};
|
||||
|
||||
@@ -397,11 +396,11 @@ struct cma_hdr {
|
||||
|
||||
struct cma_req_info {
|
||||
struct ib_device *device;
|
||||
int port;
|
||||
union ib_gid local_gid;
|
||||
__be64 service_id;
|
||||
int port;
|
||||
bool has_gid;
|
||||
u16 pkey;
|
||||
bool has_gid:1;
|
||||
};
|
||||
|
||||
static int cma_comp(struct rdma_id_private *id_priv, enum rdma_cm_state comp)
|
||||
@@ -492,7 +491,6 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
|
||||
{
|
||||
cma_ref_dev(cma_dev);
|
||||
id_priv->cma_dev = cma_dev;
|
||||
id_priv->gid_type = 0;
|
||||
id_priv->id.device = cma_dev->device;
|
||||
id_priv->id.route.addr.dev_addr.transport =
|
||||
rdma_node_get_transport(cma_dev->device->node_type);
|
||||
@@ -602,46 +600,53 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int cma_validate_port(struct ib_device *device, u8 port,
|
||||
enum ib_gid_type gid_type,
|
||||
union ib_gid *gid,
|
||||
struct rdma_id_private *id_priv)
|
||||
static const struct ib_gid_attr *
|
||||
cma_validate_port(struct ib_device *device, u8 port,
|
||||
enum ib_gid_type gid_type,
|
||||
union ib_gid *gid,
|
||||
struct rdma_id_private *id_priv)
|
||||
{
|
||||
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
|
||||
int bound_if_index = dev_addr->bound_dev_if;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
int dev_type = dev_addr->dev_type;
|
||||
if_t ndev = NULL;
|
||||
int ret = -ENODEV;
|
||||
|
||||
if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port))
|
||||
return ret;
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
|
||||
return ret;
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if (dev_type == ARPHRD_ETHER && rdma_protocol_roce(device, port)) {
|
||||
ndev = dev_get_by_index(dev_addr->net, bound_if_index);
|
||||
if (!ndev)
|
||||
return ret;
|
||||
return ERR_PTR(-ENODEV);
|
||||
} else {
|
||||
gid_type = IB_GID_TYPE_IB;
|
||||
}
|
||||
|
||||
ret = ib_find_cached_gid_by_port(device, gid, gid_type, port,
|
||||
ndev, NULL);
|
||||
|
||||
sgid_attr = rdma_find_gid_by_port(device, gid, gid_type, port, ndev);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
return sgid_attr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
static void cma_bind_sgid_attr(struct rdma_id_private *id_priv,
|
||||
const struct ib_gid_attr *sgid_attr)
|
||||
{
|
||||
WARN_ON(id_priv->id.route.addr.dev_addr.sgid_attr);
|
||||
id_priv->id.route.addr.dev_addr.sgid_attr = sgid_attr;
|
||||
}
|
||||
|
||||
static int cma_acquire_dev(struct rdma_id_private *id_priv,
|
||||
struct rdma_id_private *listen_id_priv)
|
||||
const struct rdma_id_private *listen_id_priv)
|
||||
{
|
||||
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
struct cma_device *cma_dev;
|
||||
union ib_gid gid, iboe_gid, *gidp;
|
||||
enum ib_gid_type gid_type;
|
||||
int ret = -ENODEV;
|
||||
u8 port;
|
||||
|
||||
@@ -660,21 +665,23 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
|
||||
cma_dev = listen_id_priv->cma_dev;
|
||||
port = listen_id_priv->id.port_num;
|
||||
|
||||
if (rdma_is_port_valid(cma_dev->device, port)) {
|
||||
gidp = rdma_protocol_roce(cma_dev->device, port) ?
|
||||
&iboe_gid : &gid;
|
||||
if (!rdma_is_port_valid(cma_dev->device, port))
|
||||
goto skip_listen_id;
|
||||
|
||||
ret = cma_validate_port(cma_dev->device, port,
|
||||
rdma_protocol_ib(cma_dev->device, port) ?
|
||||
IB_GID_TYPE_IB :
|
||||
listen_id_priv->gid_type, gidp, id_priv);
|
||||
if (!ret) {
|
||||
id_priv->id.port_num = port;
|
||||
goto out;
|
||||
}
|
||||
gidp = rdma_protocol_roce(cma_dev->device, port) ?
|
||||
&iboe_gid : &gid;
|
||||
gid_type = listen_id_priv->gid_type;
|
||||
sgid_attr = cma_validate_port(cma_dev->device, port,
|
||||
gid_type, gidp, id_priv);
|
||||
if (!IS_ERR(sgid_attr)) {
|
||||
id_priv->id.port_num = port;
|
||||
cma_bind_sgid_attr(id_priv, sgid_attr);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
skip_listen_id:
|
||||
list_for_each_entry(cma_dev, &dev_list, list) {
|
||||
for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
|
||||
if (listen_id_priv &&
|
||||
@@ -684,14 +691,13 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
|
||||
|
||||
gidp = rdma_protocol_roce(cma_dev->device, port) ?
|
||||
&iboe_gid : &gid;
|
||||
|
||||
ret = cma_validate_port(cma_dev->device, port,
|
||||
rdma_protocol_ib(cma_dev->device, port) ?
|
||||
IB_GID_TYPE_IB :
|
||||
cma_dev->default_gid_type[port - 1],
|
||||
gidp, id_priv);
|
||||
if (!ret) {
|
||||
gid_type = cma_dev->default_gid_type[port - 1];
|
||||
sgid_attr = cma_validate_port(cma_dev->device, port,
|
||||
gid_type, gidp, id_priv);
|
||||
if (!IS_ERR(sgid_attr)) {
|
||||
id_priv->id.port_num = port;
|
||||
cma_bind_sgid_attr(id_priv, sgid_attr);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -733,8 +739,8 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
|
||||
|
||||
if (ib_get_cached_port_state(cur_dev->device, p, &port_state))
|
||||
continue;
|
||||
for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i,
|
||||
&gid, NULL);
|
||||
for (i = 0; !rdma_query_gid(cur_dev->device,
|
||||
p, i, &gid);
|
||||
i++) {
|
||||
if (!memcmp(&gid, dgid, sizeof(gid))) {
|
||||
cma_dev = cur_dev;
|
||||
@@ -1042,21 +1048,21 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_init_qp_attr);
|
||||
|
||||
static inline int cma_zero_addr(struct sockaddr *addr)
|
||||
static inline bool cma_zero_addr(const struct sockaddr *addr)
|
||||
{
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
return ipv4_is_zeronet(((struct sockaddr_in *)addr)->sin_addr.s_addr);
|
||||
case AF_INET6:
|
||||
return ipv6_addr_any(&((struct sockaddr_in6 *) addr)->sin6_addr);
|
||||
return ipv6_addr_any(&((struct sockaddr_in6 *)addr)->sin6_addr);
|
||||
case AF_IB:
|
||||
return ib_addr_any(&((struct sockaddr_ib *) addr)->sib_addr);
|
||||
return ib_addr_any(&((struct sockaddr_ib *)addr)->sib_addr);
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int cma_loopback_addr(struct sockaddr *addr)
|
||||
static inline bool cma_loopback_addr(const struct sockaddr *addr)
|
||||
{
|
||||
switch (addr->sa_family) {
|
||||
#ifdef INET
|
||||
@@ -1065,20 +1071,23 @@ static inline int cma_loopback_addr(struct sockaddr *addr)
|
||||
* not present if INET is not included.
|
||||
*/
|
||||
case AF_INET:
|
||||
return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr);
|
||||
return ipv4_is_loopback(
|
||||
((struct sockaddr_in *)addr)->sin_addr.s_addr);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
return ipv6_addr_loopback(&((struct sockaddr_in6 *) addr)->sin6_addr);
|
||||
return ipv6_addr_loopback(
|
||||
&((struct sockaddr_in6 *)addr)->sin6_addr);
|
||||
#endif
|
||||
case AF_IB:
|
||||
return ib_addr_loopback(&((struct sockaddr_ib *) addr)->sib_addr);
|
||||
return ib_addr_loopback(
|
||||
&((struct sockaddr_ib *)addr)->sib_addr);
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool cma_any_addr(struct vnet *vnet, struct sockaddr *addr)
|
||||
static inline bool cma_any_addr(struct vnet *vnet, const struct sockaddr *addr)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
@@ -1107,7 +1116,7 @@ static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst)
|
||||
}
|
||||
}
|
||||
|
||||
static __be16 cma_port(struct sockaddr *addr)
|
||||
static __be16 cma_port(const struct sockaddr *addr)
|
||||
{
|
||||
struct sockaddr_ib *sib;
|
||||
|
||||
@@ -1125,15 +1134,15 @@ static __be16 cma_port(struct sockaddr *addr)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int cma_any_port(struct sockaddr *addr)
|
||||
static inline int cma_any_port(const struct sockaddr *addr)
|
||||
{
|
||||
return !cma_port(addr);
|
||||
}
|
||||
|
||||
static void cma_save_ib_info(struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr,
|
||||
struct rdma_cm_id *listen_id,
|
||||
struct sa_path_rec *path)
|
||||
const struct rdma_cm_id *listen_id,
|
||||
const struct sa_path_rec *path)
|
||||
{
|
||||
struct sockaddr_ib *listen_ib, *ib;
|
||||
|
||||
@@ -1299,7 +1308,7 @@ static int sdp_save_ip_info(struct sockaddr *src_addr,
|
||||
|
||||
static int cma_save_ip_info(struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr,
|
||||
struct ib_cm_event *ib_event,
|
||||
const struct ib_cm_event *ib_event,
|
||||
__be64 service_id)
|
||||
{
|
||||
struct cma_hdr *hdr;
|
||||
@@ -1333,8 +1342,8 @@ static int cma_save_ip_info(struct sockaddr *src_addr,
|
||||
|
||||
static int cma_save_net_info(struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr,
|
||||
struct rdma_cm_id *listen_id,
|
||||
struct ib_cm_event *ib_event,
|
||||
const struct rdma_cm_id *listen_id,
|
||||
const struct ib_cm_event *ib_event,
|
||||
sa_family_t sa_family, __be64 service_id)
|
||||
{
|
||||
if (sa_family == AF_IB) {
|
||||
@@ -1523,27 +1532,23 @@ static bool validate_net_dev(if_t net_dev,
|
||||
}
|
||||
|
||||
static if_t
|
||||
roce_get_net_dev_by_cm_event(struct ib_device *device, u8 port_num,
|
||||
const struct ib_cm_event *ib_event)
|
||||
roce_get_net_dev_by_cm_event(const struct ib_cm_event *ib_event)
|
||||
{
|
||||
struct ib_gid_attr sgid_attr;
|
||||
union ib_gid sgid;
|
||||
int err = -EINVAL;
|
||||
const struct ib_gid_attr *sgid_attr = NULL;
|
||||
|
||||
if (ib_event->event == IB_CM_REQ_RECEIVED) {
|
||||
err = ib_get_cached_gid(device, port_num,
|
||||
ib_event->param.req_rcvd.ppath_sgid_index, &sgid, &sgid_attr);
|
||||
} else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
|
||||
err = ib_get_cached_gid(device, port_num,
|
||||
ib_event->param.sidr_req_rcvd.sgid_index, &sgid, &sgid_attr);
|
||||
}
|
||||
if (err)
|
||||
return (NULL);
|
||||
return (sgid_attr.ndev);
|
||||
if (ib_event->event == IB_CM_REQ_RECEIVED)
|
||||
sgid_attr = ib_event->param.req_rcvd.ppath_sgid_attr;
|
||||
else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED)
|
||||
sgid_attr = ib_event->param.sidr_req_rcvd.sgid_attr;
|
||||
|
||||
if (!sgid_attr)
|
||||
return NULL;
|
||||
dev_hold(sgid_attr->ndev);
|
||||
return sgid_attr->ndev;
|
||||
}
|
||||
|
||||
static if_t cma_get_net_dev(struct ib_cm_event *ib_event,
|
||||
const struct cma_req_info *req)
|
||||
static if_t cma_get_net_dev(const struct ib_cm_event *ib_event,
|
||||
const struct cma_req_info *req)
|
||||
{
|
||||
struct sockaddr_storage listen_addr_storage, src_addr_storage;
|
||||
struct sockaddr *listen_addr = (struct sockaddr *)&listen_addr_storage,
|
||||
@@ -1558,14 +1563,13 @@ static if_t cma_get_net_dev(struct ib_cm_event *ib_event,
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (rdma_protocol_roce(req->device, req->port)) {
|
||||
net_dev = roce_get_net_dev_by_cm_event(req->device, req->port,
|
||||
ib_event);
|
||||
} else {
|
||||
if (rdma_protocol_roce(req->device, req->port))
|
||||
net_dev = roce_get_net_dev_by_cm_event(ib_event);
|
||||
else
|
||||
net_dev = ib_get_net_dev_by_params(req->device, req->port,
|
||||
req->pkey,
|
||||
gid, listen_addr);
|
||||
}
|
||||
|
||||
if (!net_dev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -1686,14 +1690,20 @@ static bool cma_match_net_dev(const struct rdma_cm_id *id,
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/* This request is an AF_IB request or a RoCE request */
|
||||
return (addr->src_addr.ss_family == AF_IB ||
|
||||
rdma_protocol_roce(id->device, port_num));
|
||||
/* This request is an AF_IB request */
|
||||
return (addr->src_addr.ss_family == AF_IB);
|
||||
}
|
||||
|
||||
return !addr->dev_addr.bound_dev_if ||
|
||||
(net_eq(dev_net(net_dev), addr->dev_addr.net) &&
|
||||
addr->dev_addr.bound_dev_if == if_getindex(net_dev));
|
||||
/*
|
||||
* Net namespaces must match, and if the listner is listening
|
||||
* on a specific netdevice than netdevice must match as well.
|
||||
*/
|
||||
if (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
|
||||
(!!addr->dev_addr.bound_dev_if ==
|
||||
(addr->dev_addr.bound_dev_if == if_getindex(net_dev))))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct rdma_id_private *cma_find_listener(
|
||||
@@ -1726,9 +1736,10 @@ static struct rdma_id_private *cma_find_listener(
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *ib_event,
|
||||
if_t *net_dev)
|
||||
static struct rdma_id_private *
|
||||
cma_ib_id_from_event(struct ib_cm_id *cm_id,
|
||||
const struct ib_cm_event *ib_event,
|
||||
if_t *net_dev)
|
||||
{
|
||||
struct cma_req_info req;
|
||||
struct rdma_bind_list *bind_list;
|
||||
@@ -1749,10 +1760,6 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
|
||||
if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
|
||||
/* Assuming the protocol is AF_IB */
|
||||
*net_dev = NULL;
|
||||
} else if (rdma_protocol_roce(req.device, req.port)) {
|
||||
/* TODO find the net dev matching the request parameters
|
||||
* through the RoCE GID table */
|
||||
*net_dev = NULL;
|
||||
} else {
|
||||
return ERR_CAST(*net_dev);
|
||||
}
|
||||
@@ -1851,6 +1858,21 @@ static void cma_release_port(struct rdma_id_private *id_priv)
|
||||
mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
static void cma_leave_roce_mc_group(struct rdma_id_private *id_priv,
|
||||
struct cma_multicast *mc)
|
||||
{
|
||||
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
|
||||
if_t ndev = NULL;
|
||||
|
||||
if (dev_addr->bound_dev_if)
|
||||
ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
|
||||
if (ndev) {
|
||||
cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, false);
|
||||
dev_put(ndev);
|
||||
}
|
||||
kref_put(&mc->mcref, release_mc);
|
||||
}
|
||||
|
||||
static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
|
||||
{
|
||||
struct cma_multicast *mc;
|
||||
@@ -1864,22 +1886,7 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
|
||||
ib_sa_free_multicast(mc->multicast.ib);
|
||||
kfree(mc);
|
||||
} else {
|
||||
if (mc->igmp_joined) {
|
||||
struct rdma_dev_addr *dev_addr =
|
||||
&id_priv->id.route.addr.dev_addr;
|
||||
if_t ndev = NULL;
|
||||
|
||||
if (dev_addr->bound_dev_if)
|
||||
ndev = dev_get_by_index(dev_addr->net,
|
||||
dev_addr->bound_dev_if);
|
||||
if (ndev) {
|
||||
cma_igmp_send(ndev,
|
||||
&mc->multicast.ib->rec.mgid,
|
||||
false);
|
||||
dev_put(ndev);
|
||||
}
|
||||
}
|
||||
kref_put(&mc->mcref, release_mc);
|
||||
cma_leave_roce_mc_group(id_priv, mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1920,6 +1927,10 @@ void rdma_destroy_id(struct rdma_cm_id *id)
|
||||
cma_deref_id(id_priv->id.context);
|
||||
|
||||
kfree(id_priv->id.route.path_rec);
|
||||
|
||||
if (id_priv->id.route.addr.dev_addr.sgid_attr)
|
||||
rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
|
||||
|
||||
kfree(id_priv);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_destroy_id);
|
||||
@@ -1956,7 +1967,7 @@ static int sdp_verify_rep(const struct sdp_hah *data)
|
||||
}
|
||||
|
||||
static void cma_set_rep_event_data(struct rdma_cm_event *event,
|
||||
struct ib_cm_rep_event_param *rep_data,
|
||||
const struct ib_cm_rep_event_param *rep_data,
|
||||
void *private_data)
|
||||
{
|
||||
event->param.conn.private_data = private_data;
|
||||
@@ -1969,10 +1980,11 @@ static void cma_set_rep_event_data(struct rdma_cm_event *event,
|
||||
event->param.conn.qp_num = rep_data->remote_qpn;
|
||||
}
|
||||
|
||||
static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
static int cma_ib_handler(struct ib_cm_id *cm_id,
|
||||
const struct ib_cm_event *ib_event)
|
||||
{
|
||||
struct rdma_id_private *id_priv = cm_id->context;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
@@ -1982,7 +1994,6 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
id_priv->state != RDMA_CM_DISCONNECT))
|
||||
goto out;
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
switch (ib_event->event) {
|
||||
case IB_CM_REQ_ERROR:
|
||||
case IB_CM_REP_ERROR:
|
||||
@@ -2054,9 +2065,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
|
||||
struct ib_cm_event *ib_event,
|
||||
if_t net_dev)
|
||||
static struct rdma_id_private *
|
||||
cma_ib_new_conn_id(const struct rdma_cm_id *listen_id,
|
||||
const struct ib_cm_event *ib_event,
|
||||
if_t net_dev)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
struct rdma_cm_id *id;
|
||||
@@ -2115,9 +2127,10 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
|
||||
struct ib_cm_event *ib_event,
|
||||
if_t net_dev)
|
||||
static struct rdma_id_private *
|
||||
cma_ib_new_udp_id(const struct rdma_cm_id *listen_id,
|
||||
const struct ib_cm_event *ib_event,
|
||||
if_t net_dev)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
struct rdma_cm_id *id;
|
||||
@@ -2156,7 +2169,7 @@ err:
|
||||
}
|
||||
|
||||
static void cma_set_req_event_data(struct rdma_cm_event *event,
|
||||
struct ib_cm_req_event_param *req_data,
|
||||
const struct ib_cm_req_event_param *req_data,
|
||||
void *private_data, int offset)
|
||||
{
|
||||
event->param.conn.private_data = (char *)private_data + offset;
|
||||
@@ -2170,7 +2183,8 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
|
||||
event->param.conn.qp_num = req_data->remote_qpn;
|
||||
}
|
||||
|
||||
static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
|
||||
static int cma_ib_check_req_qp_type(const struct rdma_cm_id *id,
|
||||
const struct ib_cm_event *ib_event)
|
||||
{
|
||||
return (((ib_event->event == IB_CM_REQ_RECEIVED) &&
|
||||
(ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
|
||||
@@ -2179,19 +2193,20 @@ static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_e
|
||||
(!id->qp_type));
|
||||
}
|
||||
|
||||
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
static int cma_ib_req_handler(struct ib_cm_id *cm_id,
|
||||
const struct ib_cm_event *ib_event)
|
||||
{
|
||||
struct rdma_id_private *listen_id, *conn_id = NULL;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
if_t net_dev;
|
||||
u8 offset;
|
||||
int ret;
|
||||
|
||||
listen_id = cma_id_from_event(cm_id, ib_event, &net_dev);
|
||||
listen_id = cma_ib_id_from_event(cm_id, ib_event, &net_dev);
|
||||
if (IS_ERR(listen_id))
|
||||
return PTR_ERR(listen_id);
|
||||
|
||||
if (!cma_check_req_qp_type(&listen_id->id, ib_event)) {
|
||||
if (!cma_ib_check_req_qp_type(&listen_id->id, ib_event)) {
|
||||
ret = -EINVAL;
|
||||
goto net_dev_put;
|
||||
}
|
||||
@@ -2202,16 +2217,15 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
offset = cma_user_data_offset(listen_id);
|
||||
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
|
||||
if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
|
||||
conn_id = cma_new_udp_id(&listen_id->id, ib_event, net_dev);
|
||||
conn_id = cma_ib_new_udp_id(&listen_id->id, ib_event, net_dev);
|
||||
event.param.ud.private_data = (char *)ib_event->private_data + offset;
|
||||
event.param.ud.private_data_len =
|
||||
IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset;
|
||||
} else {
|
||||
conn_id = cma_new_conn_id(&listen_id->id, ib_event, net_dev);
|
||||
conn_id = cma_ib_new_conn_id(&listen_id->id, ib_event, net_dev);
|
||||
cma_set_req_event_data(&event, &ib_event->param.req_rcvd,
|
||||
ib_event->private_data, offset);
|
||||
}
|
||||
@@ -2311,7 +2325,7 @@ EXPORT_SYMBOL(rdma_read_gids);
|
||||
static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
|
||||
{
|
||||
struct rdma_id_private *id_priv = iw_id->context;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
int ret = 0;
|
||||
struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
|
||||
struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
|
||||
@@ -2320,7 +2334,6 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
|
||||
if (id_priv->state != RDMA_CM_CONNECT)
|
||||
goto out;
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
switch (iw_event->event) {
|
||||
case IW_CM_EVENT_CLOSE:
|
||||
event.event = RDMA_CM_EVENT_DISCONNECTED;
|
||||
@@ -2380,11 +2393,17 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
|
||||
{
|
||||
struct rdma_cm_id *new_cm_id;
|
||||
struct rdma_id_private *listen_id, *conn_id;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
int ret = -ECONNABORTED;
|
||||
struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
|
||||
struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
|
||||
|
||||
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
|
||||
event.param.conn.private_data = iw_event->private_data;
|
||||
event.param.conn.private_data_len = iw_event->private_data_len;
|
||||
event.param.conn.initiator_depth = iw_event->ird;
|
||||
event.param.conn.responder_resources = iw_event->ord;
|
||||
|
||||
listen_id = cm_id->context;
|
||||
|
||||
mutex_lock(&listen_id->handler_mutex);
|
||||
@@ -2425,13 +2444,6 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
|
||||
memcpy(cma_src_addr(conn_id), laddr, rdma_addr_size(laddr));
|
||||
memcpy(cma_dst_addr(conn_id), raddr, rdma_addr_size(raddr));
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
|
||||
event.param.conn.private_data = iw_event->private_data;
|
||||
event.param.conn.private_data_len = iw_event->private_data_len;
|
||||
event.param.conn.initiator_depth = iw_event->ird;
|
||||
event.param.conn.responder_resources = iw_event->ord;
|
||||
|
||||
/*
|
||||
* Protect against the user destroying conn_id from another thread
|
||||
* until we're done accessing it.
|
||||
@@ -2464,7 +2476,8 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
|
||||
|
||||
addr = cma_src_addr(id_priv);
|
||||
svc_id = rdma_get_service_id(&id_priv->id, addr);
|
||||
id = ib_cm_insert_listen(id_priv->id.device, cma_req_handler, svc_id);
|
||||
id = ib_cm_insert_listen(id_priv->id.device,
|
||||
cma_ib_req_handler, svc_id);
|
||||
if (IS_ERR(id))
|
||||
return PTR_ERR(id);
|
||||
id_priv->cm_id.ib = id;
|
||||
@@ -2786,8 +2799,6 @@ cma_iboe_set_path_rec_l2_fields(struct rdma_id_private *id_priv)
|
||||
route->path_rec->rec_type = sa_conv_gid_to_pathrec_type(gid_type);
|
||||
|
||||
route->path_rec->roce.route_resolved = true;
|
||||
sa_path_set_ndev(route->path_rec, addr->dev_addr.net);
|
||||
sa_path_set_ifindex(route->path_rec, if_getindex(ndev));
|
||||
sa_path_set_dmac(route->path_rec, addr->dev_addr.dst_dev_addr);
|
||||
return ndev;
|
||||
}
|
||||
@@ -3007,7 +3018,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv)
|
||||
p = 1;
|
||||
|
||||
port_found:
|
||||
ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid, NULL);
|
||||
ret = rdma_query_gid(cma_dev->device, p, 0, &gid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -3033,9 +3044,8 @@ static void addr_handler(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *dev_addr, void *context)
|
||||
{
|
||||
struct rdma_id_private *id_priv = context;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY,
|
||||
RDMA_CM_ADDR_RESOLVED))
|
||||
@@ -3120,7 +3130,7 @@ err:
|
||||
}
|
||||
|
||||
static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr)
|
||||
const struct sockaddr *dst_addr)
|
||||
{
|
||||
if (!src_addr || !src_addr->sa_family) {
|
||||
src_addr = (struct sockaddr *) &id->route.addr.src_addr;
|
||||
@@ -3141,32 +3151,26 @@ static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
||||
}
|
||||
|
||||
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr, int timeout_ms)
|
||||
const struct sockaddr *dst_addr, int timeout_ms)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
struct vnet *vnet = id->route.addr.dev_addr.net;
|
||||
int ret;
|
||||
|
||||
id_priv = container_of(id, struct rdma_id_private, id);
|
||||
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
|
||||
if (id_priv->state == RDMA_CM_IDLE) {
|
||||
ret = cma_bind_addr(id, src_addr, dst_addr);
|
||||
if (ret) {
|
||||
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (cma_family(id_priv) != dst_addr->sa_family) {
|
||||
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
|
||||
if (cma_family(id_priv) != dst_addr->sa_family)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) {
|
||||
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
|
||||
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
|
||||
atomic_inc(&id_priv->refcount);
|
||||
if (cma_any_addr(vnet, dst_addr)) {
|
||||
ret = cma_resolve_loopback(id_priv);
|
||||
@@ -3511,7 +3515,7 @@ static int cma_get_port(struct rdma_id_private *id_priv)
|
||||
}
|
||||
|
||||
static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
|
||||
struct sockaddr *addr)
|
||||
const struct sockaddr *addr)
|
||||
{
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
@@ -3715,18 +3719,18 @@ static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv)
|
||||
}
|
||||
|
||||
static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *ib_event)
|
||||
const struct ib_cm_event *ib_event)
|
||||
{
|
||||
struct rdma_id_private *id_priv = cm_id->context;
|
||||
struct rdma_cm_event event;
|
||||
struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
|
||||
struct rdma_cm_event event = {};
|
||||
const struct ib_cm_sidr_rep_event_param *rep =
|
||||
&ib_event->param.sidr_rep_rcvd;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&id_priv->handler_mutex);
|
||||
if (id_priv->state != RDMA_CM_CONNECT)
|
||||
goto out;
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
switch (ib_event->event) {
|
||||
case IB_CM_SIDR_REQ_ERROR:
|
||||
event.event = RDMA_CM_EVENT_UNREACHABLE;
|
||||
@@ -3749,7 +3753,8 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
|
||||
ret = ib_init_ah_attr_from_path(id_priv->id.device,
|
||||
id_priv->id.port_num,
|
||||
id_priv->id.route.path_rec,
|
||||
&event.param.ud.ah_attr);
|
||||
&event.param.ud.ah_attr,
|
||||
rep->sgid_attr);
|
||||
if (ret) {
|
||||
event.event = RDMA_CM_EVENT_ADDR_ERROR;
|
||||
event.status = ret;
|
||||
@@ -3767,6 +3772,8 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
|
||||
}
|
||||
|
||||
ret = id_priv->id.event_handler(&id_priv->id, &event);
|
||||
|
||||
rdma_destroy_ah_attr(&event.param.ud.ah_attr);
|
||||
if (ret) {
|
||||
/* Destroy the CM ID by returning a non-zero value. */
|
||||
id_priv->cm_id.ib = NULL;
|
||||
@@ -3823,6 +3830,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
|
||||
id_priv->cm_id.ib = id;
|
||||
|
||||
req.path = id_priv->id.route.path_rec;
|
||||
req.sgid_attr = id_priv->id.route.addr.dev_addr.sgid_attr;
|
||||
req.service_id = rdma_get_service_id(&id_priv->id, cma_dst_addr(id_priv));
|
||||
req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8);
|
||||
req.max_cm_retries = CMA_MAX_CM_RETRIES;
|
||||
@@ -3884,6 +3892,8 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
|
||||
if (route->num_paths == 2)
|
||||
req.alternate_path = &route->path_rec[1];
|
||||
|
||||
req.ppath_sgid_attr = id_priv->id.route.addr.dev_addr.sgid_attr;
|
||||
/* Alternate path SGID attribute currently unsupported */
|
||||
req.service_id = rdma_get_service_id(&id_priv->id, cma_dst_addr(id_priv));
|
||||
req.qp_num = id_priv->qp_num;
|
||||
req.qp_type = id_priv->id.qp_type;
|
||||
@@ -4187,7 +4197,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
|
||||
{
|
||||
struct rdma_id_private *id_priv;
|
||||
struct cma_multicast *mc = multicast->context;
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
int ret = 0;
|
||||
|
||||
id_priv = mc->id_priv;
|
||||
@@ -4204,7 +4214,6 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
|
||||
be16_to_cpu(multicast->rec.mlid));
|
||||
mutex_unlock(&id_priv->qp_mutex);
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
event.status = status;
|
||||
event.param.ud.private_data = mc->context;
|
||||
if (!status) {
|
||||
@@ -4233,6 +4242,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
|
||||
event.event = RDMA_CM_EVENT_MULTICAST_ERROR;
|
||||
|
||||
ret = id_priv->id.event_handler(&id_priv->id, &event);
|
||||
|
||||
rdma_destroy_ah_attr(&event.param.ud.ah_attr);
|
||||
if (ret) {
|
||||
cma_exch(id_priv, RDMA_CM_DESTROYING);
|
||||
mutex_unlock(&id_priv->handler_mutex);
|
||||
@@ -4420,8 +4431,6 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
|
||||
if (!send_only) {
|
||||
err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
|
||||
true);
|
||||
if (!err)
|
||||
mc->igmp_joined = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -4473,26 +4482,29 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
|
||||
memcpy(&mc->addr, addr, rdma_addr_size(addr));
|
||||
mc->context = context;
|
||||
mc->id_priv = id_priv;
|
||||
mc->igmp_joined = false;
|
||||
mc->join_state = join_state;
|
||||
spin_lock(&id_priv->lock);
|
||||
list_add(&mc->list, &id_priv->mc_list);
|
||||
spin_unlock(&id_priv->lock);
|
||||
|
||||
if (rdma_protocol_roce(id->device, id->port_num)) {
|
||||
kref_init(&mc->mcref);
|
||||
ret = cma_iboe_join_multicast(id_priv, mc);
|
||||
} else if (rdma_cap_ib_mcast(id->device, id->port_num))
|
||||
if (ret)
|
||||
goto out_err;
|
||||
} else if (rdma_cap_ib_mcast(id->device, id->port_num)) {
|
||||
ret = cma_join_ib_multicast(id_priv, mc);
|
||||
else
|
||||
if (ret)
|
||||
goto out_err;
|
||||
} else {
|
||||
ret = -ENOSYS;
|
||||
|
||||
if (ret) {
|
||||
spin_lock_irq(&id_priv->lock);
|
||||
list_del(&mc->list);
|
||||
spin_unlock_irq(&id_priv->lock);
|
||||
kfree(mc);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
spin_lock(&id_priv->lock);
|
||||
list_add(&mc->list, &id_priv->mc_list);
|
||||
spin_unlock(&id_priv->lock);
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
kfree(mc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_join_multicast);
|
||||
@@ -4520,23 +4532,7 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
|
||||
ib_sa_free_multicast(mc->multicast.ib);
|
||||
kfree(mc);
|
||||
} else if (rdma_protocol_roce(id->device, id->port_num)) {
|
||||
if (mc->igmp_joined) {
|
||||
struct rdma_dev_addr *dev_addr =
|
||||
&id->route.addr.dev_addr;
|
||||
if_t ndev = NULL;
|
||||
|
||||
if (dev_addr->bound_dev_if)
|
||||
ndev = dev_get_by_index(dev_addr->net,
|
||||
dev_addr->bound_dev_if);
|
||||
if (ndev) {
|
||||
cma_igmp_send(ndev,
|
||||
&mc->multicast.ib->rec.mgid,
|
||||
false);
|
||||
dev_put(ndev);
|
||||
}
|
||||
mc->igmp_joined = false;
|
||||
}
|
||||
kref_put(&mc->mcref, release_mc);
|
||||
cma_leave_roce_mc_group(id_priv, mc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -4681,7 +4677,7 @@ free_cma_dev:
|
||||
|
||||
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
|
||||
{
|
||||
struct rdma_cm_event event;
|
||||
struct rdma_cm_event event = {};
|
||||
enum rdma_cm_state state;
|
||||
int ret = 0;
|
||||
|
||||
@@ -4697,7 +4693,6 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
|
||||
if (!cma_comp(id_priv, RDMA_CM_DEVICE_REMOVAL))
|
||||
goto out;
|
||||
|
||||
memset(&event, 0, sizeof event);
|
||||
event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
|
||||
ret = id_priv->id.event_handler(&id_priv->id, &event);
|
||||
out:
|
||||
|
||||
@@ -96,8 +96,6 @@ static int ib_device_check_mandatory(struct ib_device *device)
|
||||
IB_MANDATORY_FUNC(query_pkey),
|
||||
IB_MANDATORY_FUNC(alloc_pd),
|
||||
IB_MANDATORY_FUNC(dealloc_pd),
|
||||
IB_MANDATORY_FUNC(create_ah),
|
||||
IB_MANDATORY_FUNC(destroy_ah),
|
||||
IB_MANDATORY_FUNC(create_qp),
|
||||
IB_MANDATORY_FUNC(modify_qp),
|
||||
IB_MANDATORY_FUNC(destroy_qp),
|
||||
@@ -675,25 +673,6 @@ int ib_query_port(struct ib_device *device,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_query_port);
|
||||
|
||||
/**
|
||||
* ib_query_gid - Get GID table entry
|
||||
* @device:Device to query
|
||||
* @port_num:Port number to query
|
||||
* @index:GID table index to query
|
||||
* @gid:Returned GID
|
||||
* @attr: Returned GID attributes related to this GID index (only in RoCE).
|
||||
* NULL means ignore.
|
||||
*
|
||||
* ib_query_gid() fetches the specified GID table entry from the cache.
|
||||
*/
|
||||
int ib_query_gid(struct ib_device *device,
|
||||
u8 port_num, int index, union ib_gid *gid,
|
||||
struct ib_gid_attr *attr)
|
||||
{
|
||||
return ib_get_cached_gid(device, port_num, index, gid, attr);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_query_gid);
|
||||
|
||||
/**
|
||||
* ib_enum_roce_netdev - enumerate all RoCE ports
|
||||
* @ib_dev : IB device we want to query
|
||||
@@ -868,7 +847,7 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid,
|
||||
continue;
|
||||
|
||||
for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
|
||||
ret = ib_query_gid(device, port, i, &tmp_gid, NULL);
|
||||
ret = rdma_query_gid(device, port, i, &tmp_gid);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
|
||||
|
||||
@@ -1149,7 +1149,6 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
{
|
||||
struct ib_mad_qp_info *qp_info;
|
||||
struct list_head *list;
|
||||
const struct ib_send_wr *bad_send_wr;
|
||||
struct ib_mad_agent *mad_agent;
|
||||
struct ib_sge *sge;
|
||||
unsigned long flags;
|
||||
@@ -1187,7 +1186,7 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
spin_lock_irqsave(&qp_info->send_queue.lock, flags);
|
||||
if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
|
||||
ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr.wr,
|
||||
&bad_send_wr);
|
||||
NULL);
|
||||
list = &qp_info->send_queue.list;
|
||||
} else {
|
||||
ret = 0;
|
||||
@@ -1882,8 +1881,8 @@ static inline int rcv_has_same_gid(const struct ib_mad_agent_private *mad_agent_
|
||||
const struct ib_global_route *grh =
|
||||
rdma_ah_read_grh(&attr);
|
||||
|
||||
if (ib_get_cached_gid(device, port_num,
|
||||
grh->sgid_index, &sgid, NULL))
|
||||
if (rdma_query_gid(device, port_num,
|
||||
grh->sgid_index, &sgid))
|
||||
return 0;
|
||||
return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
|
||||
16);
|
||||
@@ -2432,7 +2431,6 @@ static void ib_mad_send_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||
struct ib_mad_send_wr_private *mad_send_wr, *queued_send_wr;
|
||||
struct ib_mad_qp_info *qp_info;
|
||||
struct ib_mad_queue *send_queue;
|
||||
const struct ib_send_wr *bad_send_wr;
|
||||
struct ib_mad_send_wc mad_send_wc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
@@ -2482,7 +2480,7 @@ retry:
|
||||
|
||||
if (queued_send_wr) {
|
||||
ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr.wr,
|
||||
&bad_send_wr);
|
||||
NULL);
|
||||
if (ret) {
|
||||
dev_err(&port_priv->device->dev,
|
||||
"ib_post_send failed: %d\n", ret);
|
||||
@@ -2527,11 +2525,9 @@ static bool ib_mad_send_error(struct ib_mad_port_private *port_priv,
|
||||
if (wc->status == IB_WC_WR_FLUSH_ERR) {
|
||||
if (mad_send_wr->retry) {
|
||||
/* Repost send */
|
||||
const struct ib_send_wr *bad_send_wr;
|
||||
|
||||
mad_send_wr->retry = 0;
|
||||
ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr.wr,
|
||||
&bad_send_wr);
|
||||
NULL);
|
||||
if (!ret)
|
||||
return false;
|
||||
}
|
||||
@@ -2848,7 +2844,6 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
|
||||
struct ib_mad_private *mad_priv;
|
||||
struct ib_sge sg_list;
|
||||
struct ib_recv_wr recv_wr;
|
||||
const struct ib_recv_wr *bad_recv_wr;
|
||||
struct ib_mad_queue *recv_queue = &qp_info->recv_queue;
|
||||
|
||||
/* Initialize common scatter list fields */
|
||||
@@ -2893,7 +2888,7 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
|
||||
post = (++recv_queue->count < recv_queue->max_active);
|
||||
list_add_tail(&mad_priv->header.mad_list.list, &recv_queue->list);
|
||||
spin_unlock_irqrestore(&recv_queue->lock, flags);
|
||||
ret = ib_post_recv(qp_info->qp, &recv_wr, &bad_recv_wr);
|
||||
ret = ib_post_recv(qp_info->qp, &recv_wr, NULL);
|
||||
if (ret) {
|
||||
spin_lock_irqsave(&recv_queue->lock, flags);
|
||||
list_del(&mad_priv->header.mad_list.list);
|
||||
|
||||
@@ -719,14 +719,28 @@ int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_sa_get_mcmember_rec);
|
||||
|
||||
/**
|
||||
* ib_init_ah_from_mcmember - Initialize AH attribute from multicast
|
||||
* member record and gid of the device.
|
||||
* @device: RDMA device
|
||||
* @port_num: Port of the rdma device to consider
|
||||
* @ndev: Optional netdevice, applicable only for RoCE
|
||||
* @gid_type: GID type to consider
|
||||
* @ah_attr: AH attribute to fillup on successful completion
|
||||
*
|
||||
* ib_init_ah_from_mcmember() initializes AH attribute based on multicast
|
||||
* member record and other device properties. On success the caller is
|
||||
* responsible to call rdma_destroy_ah_attr on the ah_attr. Returns 0 on
|
||||
* success or appropriate error code.
|
||||
*
|
||||
*/
|
||||
int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_mcmember_rec *rec,
|
||||
if_t ndev,
|
||||
enum ib_gid_type gid_type,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
int ret;
|
||||
u16 gid_index;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
|
||||
/* GID table is not based on the netdevice for IB link layer,
|
||||
* so ignore ndev during search.
|
||||
@@ -736,26 +750,22 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
|
||||
else if (!rdma_protocol_roce(device, port_num))
|
||||
return -EINVAL;
|
||||
|
||||
ret = ib_find_cached_gid_by_port(device, &rec->port_gid,
|
||||
gid_type, port_num,
|
||||
ndev,
|
||||
&gid_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
sgid_attr = rdma_find_gid_by_port(device, &rec->port_gid,
|
||||
gid_type, port_num, ndev);
|
||||
if (IS_ERR(sgid_attr))
|
||||
return PTR_ERR(sgid_attr);
|
||||
|
||||
memset(ah_attr, 0, sizeof *ah_attr);
|
||||
memset(ah_attr, 0, sizeof(*ah_attr));
|
||||
ah_attr->type = rdma_ah_find_type(device, port_num);
|
||||
|
||||
rdma_ah_set_dlid(ah_attr, be16_to_cpu(rec->mlid));
|
||||
rdma_ah_set_sl(ah_attr, rec->sl);
|
||||
rdma_ah_set_port_num(ah_attr, port_num);
|
||||
rdma_ah_set_static_rate(ah_attr, rec->rate);
|
||||
|
||||
rdma_ah_set_grh(ah_attr, &rec->mgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
(u8)gid_index,
|
||||
rec->hop_limit,
|
||||
rec->traffic_class);
|
||||
rdma_move_grh_sgid_attr(ah_attr, &rec->mgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
rec->hop_limit, rec->traffic_class,
|
||||
sgid_attr);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_init_ah_from_mcmember);
|
||||
|
||||
@@ -115,23 +115,23 @@ static void update_gid(enum gid_op_type gid_op, struct ib_device *ib_dev,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
roce_gid_match_netdev(struct ib_device *ib_dev, u8 port,
|
||||
if_t idev, void *cookie)
|
||||
{
|
||||
if_t ndev = (if_t )cookie;
|
||||
if (idev == NULL)
|
||||
return (0);
|
||||
return (false);
|
||||
return (ndev == idev);
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
roce_gid_match_all(struct ib_device *ib_dev, u8 port,
|
||||
if_t idev, void *cookie)
|
||||
{
|
||||
if (idev == NULL)
|
||||
return (0);
|
||||
return (1);
|
||||
return (false);
|
||||
return (true);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -209,11 +209,10 @@ roce_gid_update_addr_callback(struct ib_device *device, u8 port,
|
||||
struct if_iter iter;
|
||||
struct ipx_entry *entry;
|
||||
VNET_ITERATOR_DECL(vnet_iter);
|
||||
struct ib_gid_attr gid_attr;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
union ib_gid gid;
|
||||
if_t ifp;
|
||||
int default_gids;
|
||||
u16 index_num;
|
||||
int i;
|
||||
|
||||
struct ipx_queue ipx_head;
|
||||
@@ -259,8 +258,9 @@ roce_gid_update_addr_callback(struct ib_device *device, u8 port,
|
||||
if (!((1UL << i) & gid_type_mask))
|
||||
continue;
|
||||
/* check if entry found */
|
||||
if (ib_find_cached_gid_by_port(device, &gid, i,
|
||||
port, entry->ndev, &index_num) == 0)
|
||||
sgid_attr = rdma_find_gid_by_port(device, &gid, i,
|
||||
port, entry->ndev);
|
||||
if (!IS_ERR(sgid_attr))
|
||||
break;
|
||||
}
|
||||
if (i != IB_GID_TYPE_SIZE)
|
||||
@@ -270,14 +270,20 @@ roce_gid_update_addr_callback(struct ib_device *device, u8 port,
|
||||
}
|
||||
|
||||
/* remove stale GIDs, if any */
|
||||
for (i = default_gids; ib_get_cached_gid(device, port, i, &gid, &gid_attr) == 0; i++) {
|
||||
for (i = default_gids;; i++) {
|
||||
union ipx_addr ipx;
|
||||
|
||||
sgid_attr = rdma_get_gid_attr(device, port, i);
|
||||
if (IS_ERR(sgid_attr))
|
||||
break;
|
||||
|
||||
ndev = sgid_attr->ndev;
|
||||
gid = sgid_attr->gid;
|
||||
rdma_put_gid_attr(sgid_attr);
|
||||
|
||||
/* check for valid network device pointer */
|
||||
ndev = gid_attr.ndev;
|
||||
if (ndev == NULL)
|
||||
continue;
|
||||
dev_put(ndev);
|
||||
|
||||
/* don't delete empty entries */
|
||||
if (rdma_is_zero_gid(&gid))
|
||||
|
||||
@@ -790,28 +790,23 @@ static u8 get_src_path_mask(struct ib_device *device, u8 port_num)
|
||||
return src_path_mask;
|
||||
}
|
||||
|
||||
static int
|
||||
roce_resolve_route_from_path(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec)
|
||||
static int roce_resolve_route_from_path(struct sa_path_rec *rec,
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
if_t resolved_dev;
|
||||
if_t ndev;
|
||||
if_t idev;
|
||||
struct rdma_dev_addr dev_addr = {
|
||||
.bound_dev_if = ((sa_path_get_ifindex(rec) >= 0) ?
|
||||
sa_path_get_ifindex(rec) : 0),
|
||||
.net = sa_path_get_ndev(rec) ?
|
||||
sa_path_get_ndev(rec) :
|
||||
&init_net
|
||||
};
|
||||
struct rdma_dev_addr dev_addr = {};
|
||||
union rdma_sockaddr sgid_addr, dgid_addr;
|
||||
int ret;
|
||||
|
||||
if (rec->roce.route_resolved)
|
||||
return 0;
|
||||
if (!attr || !attr->ndev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device->get_netdev)
|
||||
return -EOPNOTSUPP;
|
||||
dev_addr.bound_dev_if = if_getindex(attr->ndev);
|
||||
/* TODO: Use net from the ib_gid_attr once it is added to it,
|
||||
* until than, limit itself to init_net.
|
||||
*/
|
||||
dev_addr.net = &init_net;
|
||||
|
||||
rdma_gid2ip(&sgid_addr._sockaddr, &rec->sgid);
|
||||
rdma_gid2ip(&dgid_addr._sockaddr, &rec->dgid);
|
||||
@@ -827,60 +822,52 @@ roce_resolve_route_from_path(struct ib_device *device, u8 port_num,
|
||||
rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2)
|
||||
return -EINVAL;
|
||||
|
||||
idev = device->get_netdev(device, port_num);
|
||||
if (!idev)
|
||||
return -ENODEV;
|
||||
|
||||
resolved_dev = dev_get_by_index(dev_addr.net,
|
||||
dev_addr.bound_dev_if);
|
||||
if (!resolved_dev) {
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
ndev = ib_get_ndev_from_path(rec);
|
||||
rcu_read_lock();
|
||||
if ((ndev && ndev != resolved_dev) ||
|
||||
(resolved_dev != idev &&
|
||||
rdma_vlan_dev_real_dev(resolved_dev) != idev))
|
||||
ret = -EHOSTUNREACH;
|
||||
rcu_read_unlock();
|
||||
dev_put(resolved_dev);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
done:
|
||||
dev_put(idev);
|
||||
if (!ret)
|
||||
rec->roce.route_resolved = true;
|
||||
return ret;
|
||||
rec->roce.route_resolved = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_ah_attr_grh_fields(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr *gid_attr)
|
||||
{
|
||||
enum ib_gid_type type = sa_conv_pathrec_to_gid_type(rec);
|
||||
if_t ndev;
|
||||
u16 gid_index;
|
||||
int ret;
|
||||
|
||||
ndev = ib_get_ndev_from_path(rec);
|
||||
ret = ib_find_cached_gid_by_port(device, &rec->sgid, type,
|
||||
port_num, ndev, &gid_index);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!gid_attr) {
|
||||
gid_attr = rdma_find_gid_by_port(device, &rec->sgid, type,
|
||||
port_num, NULL);
|
||||
if (IS_ERR(gid_attr))
|
||||
return PTR_ERR(gid_attr);
|
||||
} else
|
||||
rdma_hold_gid_attr(gid_attr);
|
||||
|
||||
rdma_ah_set_grh(ah_attr, &rec->dgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
gid_index, rec->hop_limit,
|
||||
rec->traffic_class);
|
||||
rdma_move_grh_sgid_attr(ah_attr, &rec->dgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
rec->hop_limit, rec->traffic_class,
|
||||
gid_attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_init_ah_attr_from_path - Initialize address handle attributes based on
|
||||
* an SA path record.
|
||||
* @device: Device associated ah attributes initialization.
|
||||
* @port_num: Port on the specified device.
|
||||
* @rec: path record entry to use for ah attributes initialization.
|
||||
* @ah_attr: address handle attributes to initialization from path record.
|
||||
* @sgid_attr: SGID attribute to consider during initialization.
|
||||
*
|
||||
* When ib_init_ah_attr_from_path() 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_destroy_ah_attr() to release reference to SGID
|
||||
* attributes which are initialized using ib_init_ah_attr_from_path().
|
||||
*/
|
||||
int ib_init_ah_attr_from_path(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr *gid_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -891,7 +878,7 @@ int ib_init_ah_attr_from_path(struct ib_device *device, u8 port_num,
|
||||
rdma_ah_set_static_rate(ah_attr, rec->rate);
|
||||
|
||||
if (sa_path_is_roce(rec)) {
|
||||
ret = roce_resolve_route_from_path(device, port_num, rec);
|
||||
ret = roce_resolve_route_from_path(rec, gid_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -908,7 +895,8 @@ int ib_init_ah_attr_from_path(struct ib_device *device, u8 port_num,
|
||||
}
|
||||
|
||||
if (rec->hop_limit > 0 || sa_path_is_roce(rec))
|
||||
ret = init_ah_attr_grh_fields(device, port_num, rec, ah_attr);
|
||||
ret = init_ah_attr_grh_fields(device, port_num,
|
||||
rec, ah_attr, gid_attr);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_init_ah_attr_from_path);
|
||||
@@ -1112,8 +1100,6 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
|
||||
ARRAY_SIZE(path_rec_table),
|
||||
mad->data, &rec);
|
||||
rec.rec_type = SA_PATH_REC_TYPE_IB;
|
||||
sa_path_set_ndev(&rec, NULL);
|
||||
sa_path_set_ifindex(&rec, 0);
|
||||
sa_path_set_dmac_zero(&rec);
|
||||
|
||||
if (query->conv_pr) {
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <rdma/ib_addr.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
#include <rdma/ib_pma.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
struct ib_port;
|
||||
|
||||
@@ -368,7 +369,7 @@ static struct attribute *port_default_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static size_t print_ndev(struct ib_gid_attr *gid_attr, char *buf)
|
||||
static size_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf)
|
||||
{
|
||||
if (!gid_attr->ndev)
|
||||
return -EINVAL;
|
||||
@@ -376,33 +377,26 @@ static size_t print_ndev(struct ib_gid_attr *gid_attr, char *buf)
|
||||
return sprintf(buf, "%s\n", if_name(gid_attr->ndev));
|
||||
}
|
||||
|
||||
static size_t print_gid_type(struct ib_gid_attr *gid_attr, char *buf)
|
||||
static size_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type));
|
||||
}
|
||||
|
||||
static ssize_t _show_port_gid_attr(struct ib_port *p,
|
||||
struct port_attribute *attr,
|
||||
char *buf,
|
||||
size_t (*print)(struct ib_gid_attr *gid_attr,
|
||||
char *buf))
|
||||
static ssize_t _show_port_gid_attr(
|
||||
struct ib_port *p, struct port_attribute *attr, char *buf,
|
||||
size_t (*print)(const struct ib_gid_attr *gid_attr, char *buf))
|
||||
{
|
||||
struct port_table_attribute *tab_attr =
|
||||
container_of(attr, struct port_table_attribute, attr);
|
||||
union ib_gid gid;
|
||||
struct ib_gid_attr gid_attr = {};
|
||||
const struct ib_gid_attr *gid_attr;
|
||||
ssize_t ret;
|
||||
|
||||
ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid,
|
||||
&gid_attr);
|
||||
if (ret)
|
||||
goto err;
|
||||
gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index);
|
||||
if (IS_ERR(gid_attr))
|
||||
return PTR_ERR(gid_attr);
|
||||
|
||||
ret = print(&gid_attr, buf);
|
||||
|
||||
err:
|
||||
if (gid_attr.ndev)
|
||||
dev_put(gid_attr.ndev);
|
||||
ret = print(gid_attr, buf);
|
||||
rdma_put_gid_attr(gid_attr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -411,28 +405,28 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
|
||||
{
|
||||
struct port_table_attribute *tab_attr =
|
||||
container_of(attr, struct port_table_attribute, attr);
|
||||
union ib_gid *pgid;
|
||||
union ib_gid gid;
|
||||
const struct ib_gid_attr *gid_attr;
|
||||
ssize_t ret;
|
||||
|
||||
ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index);
|
||||
if (IS_ERR(gid_attr)) {
|
||||
const union ib_gid zgid = {};
|
||||
|
||||
/* If reading GID fails, it is likely due to GID entry being empty
|
||||
* (invalid) or reserved GID in the table.
|
||||
* User space expects to read GID table entries as long as it given
|
||||
* index is within GID table size.
|
||||
* Administrative/debugging tool fails to query rest of the GID entries
|
||||
* if it hits error while querying a GID of the given index.
|
||||
* To avoid user space throwing such error on fail to read gid, return
|
||||
* zero GID as before. This maintains backward compatibility.
|
||||
*/
|
||||
if (ret)
|
||||
pgid = &zgid;
|
||||
else
|
||||
pgid = &gid;
|
||||
return sprintf(buf, GID_PRINT_FMT"\n", GID_PRINT_ARGS(pgid->raw));
|
||||
/* If reading GID fails, it is likely due to GID entry being
|
||||
* empty (invalid) or reserved GID in the table. User space
|
||||
* expects to read GID table entries as long as it given index
|
||||
* is within GID table size. Administrative/debugging tool
|
||||
* fails to query rest of the GID entries if it hits error
|
||||
* while querying a GID of the given index. To avoid user
|
||||
* space throwing such error on fail to read gid, return zero
|
||||
* GID as before. This maintains backward compatibility.
|
||||
*/
|
||||
return sprintf(buf, "%pI6\n", zgid.raw);
|
||||
}
|
||||
|
||||
ret = sprintf(buf, GID_PRINT_FMT"\n", GID_PRINT_ARGS(gid_attr->gid.raw));
|
||||
rdma_put_gid_attr(gid_attr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t show_port_gid_attr_ndev(struct ib_port *p,
|
||||
|
||||
@@ -203,7 +203,7 @@ error:
|
||||
}
|
||||
|
||||
static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
|
||||
struct ib_cm_req_event_param *kreq)
|
||||
const struct ib_cm_req_event_param *kreq)
|
||||
{
|
||||
ureq->remote_ca_guid = kreq->remote_ca_guid;
|
||||
ureq->remote_qkey = kreq->remote_qkey;
|
||||
@@ -227,7 +227,7 @@ static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
|
||||
}
|
||||
|
||||
static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
|
||||
struct ib_cm_rep_event_param *krep)
|
||||
const struct ib_cm_rep_event_param *krep)
|
||||
{
|
||||
urep->remote_ca_guid = krep->remote_ca_guid;
|
||||
urep->remote_qkey = krep->remote_qkey;
|
||||
@@ -243,14 +243,14 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
|
||||
}
|
||||
|
||||
static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
|
||||
struct ib_cm_sidr_rep_event_param *krep)
|
||||
const struct ib_cm_sidr_rep_event_param *krep)
|
||||
{
|
||||
urep->status = krep->status;
|
||||
urep->qkey = krep->qkey;
|
||||
urep->qpn = krep->qpn;
|
||||
};
|
||||
|
||||
static int ib_ucm_event_process(struct ib_cm_event *evt,
|
||||
static int ib_ucm_event_process(const struct ib_cm_event *evt,
|
||||
struct ib_ucm_event *uvt)
|
||||
{
|
||||
void *info = NULL;
|
||||
@@ -347,7 +347,7 @@ err1:
|
||||
}
|
||||
|
||||
static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event)
|
||||
const struct ib_cm_event *event)
|
||||
{
|
||||
struct ib_ucm_event *uevent;
|
||||
struct ib_ucm_context *ctx;
|
||||
@@ -996,14 +996,11 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
|
||||
const char __user *inbuf,
|
||||
int in_len, int out_len)
|
||||
{
|
||||
struct ib_cm_sidr_req_param param;
|
||||
struct ib_cm_sidr_req_param param = {};
|
||||
struct ib_ucm_context *ctx;
|
||||
struct ib_ucm_sidr_req cmd;
|
||||
int result;
|
||||
|
||||
param.private_data = NULL;
|
||||
param.path = NULL;
|
||||
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
@@ -115,6 +115,8 @@ static DEFINE_MUTEX(mut);
|
||||
static DEFINE_IDR(ctx_idr);
|
||||
static DEFINE_IDR(multicast_idr);
|
||||
|
||||
static const struct file_operations ucma_fops;
|
||||
|
||||
static inline struct ucma_context *_ucma_find_context(int id,
|
||||
struct ucma_file *file)
|
||||
{
|
||||
@@ -1559,6 +1561,10 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
||||
f = fdget(cmd.fd);
|
||||
if (!f.file)
|
||||
return -ENOENT;
|
||||
if (f.file->f_op != &ucma_fops) {
|
||||
ret = -EINVAL;
|
||||
goto file_put;
|
||||
}
|
||||
|
||||
/* Validate current fd and prevent destruction of id. */
|
||||
ctx = ucma_get_ctx(f.file->private_data, cmd.id);
|
||||
|
||||
@@ -86,14 +86,12 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
struct ib_umem *umem;
|
||||
struct page **page_list;
|
||||
struct vm_area_struct **vma_list;
|
||||
unsigned long locked;
|
||||
unsigned long cur_base;
|
||||
unsigned long npages;
|
||||
int ret;
|
||||
int i;
|
||||
unsigned long dma_attrs = 0;
|
||||
struct scatterlist *sg, *sg_list_start;
|
||||
int need_release = 0;
|
||||
unsigned int gup_flags = FOLL_WRITE;
|
||||
|
||||
if (dmasync)
|
||||
@@ -122,12 +120,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
umem->writable = ib_access_writable(access);
|
||||
|
||||
if (access & IB_ACCESS_ON_DEMAND) {
|
||||
put_pid(umem->pid);
|
||||
ret = ib_umem_odp_get(context, umem, access);
|
||||
if (ret) {
|
||||
kfree(umem);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
if (ret)
|
||||
goto umem_kfree;
|
||||
return umem;
|
||||
}
|
||||
|
||||
@@ -135,9 +130,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
|
||||
page_list = (struct page **) __get_free_page(GFP_KERNEL);
|
||||
if (!page_list) {
|
||||
put_pid(umem->pid);
|
||||
kfree(umem);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ret = -ENOMEM;
|
||||
goto umem_kfree;
|
||||
}
|
||||
|
||||
vma_list = (struct vm_area_struct **) __get_free_page(GFP_KERNEL);
|
||||
@@ -145,34 +139,35 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
npages = ib_umem_num_pages(umem);
|
||||
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
|
||||
locked = npages + current->mm->pinned_vm;
|
||||
current->mm->pinned_vm += npages;
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
|
||||
cur_base = addr & PAGE_MASK;
|
||||
|
||||
if (npages == 0 || npages > UINT_MAX) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
goto vma;
|
||||
}
|
||||
|
||||
ret = sg_alloc_table(&umem->sg_head, npages, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto vma;
|
||||
|
||||
if (!umem->writable)
|
||||
gup_flags |= FOLL_FORCE;
|
||||
|
||||
need_release = 1;
|
||||
sg_list_start = umem->sg_head.sgl;
|
||||
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
while (npages) {
|
||||
ret = get_user_pages(cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE / sizeof (struct page *)),
|
||||
gup_flags, page_list, vma_list);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret < 0) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
goto umem_release;
|
||||
}
|
||||
|
||||
umem->npages += ret;
|
||||
cur_base += ret * PAGE_SIZE;
|
||||
@@ -185,6 +180,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
/* preparing for next loop */
|
||||
sg_list_start = sg;
|
||||
}
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
umem->nmap = ib_dma_map_sg_attrs(context->device,
|
||||
umem->sg_head.sgl,
|
||||
@@ -194,26 +190,28 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
||||
|
||||
if (umem->nmap <= 0) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
goto umem_release;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
if (need_release)
|
||||
__ib_umem_release(context->device, umem, 0);
|
||||
put_pid(umem->pid);
|
||||
kfree(umem);
|
||||
} else
|
||||
current->mm->pinned_vm = locked;
|
||||
|
||||
umem_release:
|
||||
__ib_umem_release(context->device, umem, 0);
|
||||
vma:
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
current->mm->pinned_vm -= ib_umem_num_pages(umem);
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
out:
|
||||
if (vma_list)
|
||||
free_page((unsigned long) vma_list);
|
||||
free_page((unsigned long) page_list);
|
||||
|
||||
return ret < 0 ? ERR_PTR(ret) : umem;
|
||||
umem_kfree:
|
||||
if (ret) {
|
||||
put_pid(umem->pid);
|
||||
kfree(umem);
|
||||
}
|
||||
return ret ? ERR_PTR(ret) : umem;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_get);
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,
|
||||
rbt_ib_umem_for_each_in_range(&context->umem_tree, 0,
|
||||
ULLONG_MAX,
|
||||
ib_umem_notifier_release_trampoline,
|
||||
true,
|
||||
NULL);
|
||||
up_read(&context->umem_rwsem);
|
||||
}
|
||||
@@ -206,22 +207,31 @@ static int invalidate_range_start_trampoline(struct ib_umem *item, u64 start,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
|
||||
static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
|
||||
struct mm_struct *mm,
|
||||
unsigned long start,
|
||||
unsigned long end)
|
||||
unsigned long end,
|
||||
bool blockable)
|
||||
{
|
||||
struct ib_ucontext *context = container_of(mn, struct ib_ucontext, mn);
|
||||
int ret;
|
||||
|
||||
if (!context->invalidate_range)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (blockable)
|
||||
down_read(&context->umem_rwsem);
|
||||
else if (!down_read_trylock(&context->umem_rwsem))
|
||||
return -EAGAIN;
|
||||
|
||||
ib_ucontext_notifier_start_account(context);
|
||||
down_read(&context->umem_rwsem);
|
||||
rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
|
||||
ret = rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
|
||||
end,
|
||||
invalidate_range_start_trampoline, NULL);
|
||||
invalidate_range_start_trampoline,
|
||||
blockable, NULL);
|
||||
up_read(&context->umem_rwsem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int invalidate_range_end_trampoline(struct ib_umem *item, u64 start,
|
||||
@@ -241,10 +251,15 @@ static void ib_umem_notifier_invalidate_range_end(struct mmu_notifier *mn,
|
||||
if (!context->invalidate_range)
|
||||
return;
|
||||
|
||||
/*
|
||||
* TODO: we currently bail out if there is any sleepable work to be done
|
||||
* in ib_umem_notifier_invalidate_range_start so we shouldn't really block
|
||||
* here. But this is ugly and fragile.
|
||||
*/
|
||||
down_read(&context->umem_rwsem);
|
||||
rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
|
||||
end,
|
||||
invalidate_range_end_trampoline, NULL);
|
||||
invalidate_range_end_trampoline, true, NULL);
|
||||
up_read(&context->umem_rwsem);
|
||||
ib_ucontext_notifier_end_account(context);
|
||||
}
|
||||
@@ -791,6 +806,7 @@ EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);
|
||||
int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
|
||||
u64 start, u64 last,
|
||||
umem_call_back cb,
|
||||
bool blockable,
|
||||
void *cookie)
|
||||
{
|
||||
int ret_val = 0;
|
||||
@@ -802,6 +818,9 @@ int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
|
||||
|
||||
for (node = rbt_ib_umem_iter_first(root, start, last - 1);
|
||||
node; node = next) {
|
||||
/* TODO move the blockable decision up to the callback */
|
||||
if (!blockable)
|
||||
return -EAGAIN;
|
||||
next = rbt_ib_umem_iter_next(node, start, last - 1);
|
||||
umem = container_of(node, struct ib_umem_odp, interval_tree);
|
||||
ret_val = cb(umem->umem, start, last, cookie) || ret_val;
|
||||
|
||||
@@ -254,6 +254,7 @@ static void recv_handler(struct ib_mad_agent *agent,
|
||||
packet->mad.hdr.traffic_class = grh->traffic_class;
|
||||
memcpy(packet->mad.hdr.gid, &grh->dgid, 16);
|
||||
packet->mad.hdr.flow_label = cpu_to_be32(grh->flow_label);
|
||||
rdma_destroy_ah_attr(&ah_attr);
|
||||
}
|
||||
|
||||
if (queue_packet(file, agent, packet))
|
||||
|
||||
@@ -213,7 +213,5 @@ void ib_copy_path_rec_from_user(struct sa_path_rec *dst,
|
||||
|
||||
/* TODO: No need to set this */
|
||||
sa_path_set_dmac_zero(dst);
|
||||
sa_path_set_ndev(dst, TD_TO_VNET(curthread));
|
||||
sa_path_set_ifindex(dst, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_copy_path_rec_from_user);
|
||||
@@ -355,6 +355,152 @@ EXPORT_SYMBOL(ib_dealloc_pd_user);
|
||||
|
||||
/* Address handles */
|
||||
|
||||
/**
|
||||
* rdma_copy_ah_attr - Copy rdma ah attribute from source to destination.
|
||||
* @dest: Pointer to destination ah_attr. Contents of the destination
|
||||
* pointer is assumed to be invalid and attribute are overwritten.
|
||||
* @src: Pointer to source ah_attr.
|
||||
*/
|
||||
void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
|
||||
const struct rdma_ah_attr *src)
|
||||
{
|
||||
*dest = *src;
|
||||
if (dest->grh.sgid_attr)
|
||||
rdma_hold_gid_attr(dest->grh.sgid_attr);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_copy_ah_attr);
|
||||
|
||||
/**
|
||||
* rdma_replace_ah_attr - Replace valid ah_attr with new new one.
|
||||
* @old: Pointer to existing ah_attr which needs to be replaced.
|
||||
* old is assumed to be valid or zero'd
|
||||
* @new: Pointer to the new ah_attr.
|
||||
*
|
||||
* rdma_replace_ah_attr() first releases any reference in the old ah_attr if
|
||||
* old the ah_attr is valid; after that it copies the new attribute and holds
|
||||
* the reference to the replaced ah_attr.
|
||||
*/
|
||||
void rdma_replace_ah_attr(struct rdma_ah_attr *old,
|
||||
const struct rdma_ah_attr *new)
|
||||
{
|
||||
rdma_destroy_ah_attr(old);
|
||||
*old = *new;
|
||||
if (old->grh.sgid_attr)
|
||||
rdma_hold_gid_attr(old->grh.sgid_attr);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_replace_ah_attr);
|
||||
|
||||
/**
|
||||
* rdma_move_ah_attr - Move ah_attr pointed by source to destination.
|
||||
* @dest: Pointer to destination ah_attr to copy to.
|
||||
* dest is assumed to be valid or zero'd
|
||||
* @src: Pointer to the new ah_attr.
|
||||
*
|
||||
* rdma_move_ah_attr() first releases any reference in the destination ah_attr
|
||||
* if it is valid. This also transfers ownership of internal references from
|
||||
* src to dest, making src invalid in the process. No new reference of the src
|
||||
* ah_attr is taken.
|
||||
*/
|
||||
void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src)
|
||||
{
|
||||
rdma_destroy_ah_attr(dest);
|
||||
*dest = *src;
|
||||
src->grh.sgid_attr = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_move_ah_attr);
|
||||
|
||||
/*
|
||||
* Validate that the rdma_ah_attr is valid for the device before passing it
|
||||
* off to the driver.
|
||||
*/
|
||||
static int rdma_check_ah_attr(struct ib_device *device,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
if (!rdma_is_port_valid(device, ah_attr->port_num))
|
||||
return -EINVAL;
|
||||
|
||||
if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE &&
|
||||
!(ah_attr->ah_flags & IB_AH_GRH))
|
||||
return -EINVAL;
|
||||
|
||||
if (ah_attr->grh.sgid_attr) {
|
||||
/*
|
||||
* Make sure the passed sgid_attr is consistent with the
|
||||
* parameters
|
||||
*/
|
||||
if (ah_attr->grh.sgid_attr->index != ah_attr->grh.sgid_index ||
|
||||
ah_attr->grh.sgid_attr->port_num != ah_attr->port_num)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the ah requires a GRH then ensure that sgid_attr pointer is filled in.
|
||||
* On success the caller is responsible to call rdma_unfill_sgid_attr().
|
||||
*/
|
||||
static int rdma_fill_sgid_attr(struct ib_device *device,
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr **old_sgid_attr)
|
||||
{
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
struct ib_global_route *grh;
|
||||
int ret;
|
||||
|
||||
*old_sgid_attr = ah_attr->grh.sgid_attr;
|
||||
|
||||
ret = rdma_check_ah_attr(device, ah_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(ah_attr->ah_flags & IB_AH_GRH))
|
||||
return 0;
|
||||
|
||||
grh = rdma_ah_retrieve_grh(ah_attr);
|
||||
if (grh->sgid_attr)
|
||||
return 0;
|
||||
|
||||
sgid_attr =
|
||||
rdma_get_gid_attr(device, ah_attr->port_num, grh->sgid_index);
|
||||
if (IS_ERR(sgid_attr))
|
||||
return PTR_ERR(sgid_attr);
|
||||
|
||||
/* Move ownerhip of the kref into the ah_attr */
|
||||
grh->sgid_attr = sgid_attr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rdma_unfill_sgid_attr(struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr *old_sgid_attr)
|
||||
{
|
||||
/*
|
||||
* Fill didn't change anything, the caller retains ownership of
|
||||
* whatever it passed
|
||||
*/
|
||||
if (ah_attr->grh.sgid_attr == old_sgid_attr)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Otherwise, we need to undo what rdma_fill_sgid_attr so the caller
|
||||
* doesn't see any change in the rdma_ah_attr. If we get here
|
||||
* old_sgid_attr is NULL.
|
||||
*/
|
||||
rdma_destroy_ah_attr(ah_attr);
|
||||
}
|
||||
|
||||
static const struct ib_gid_attr *
|
||||
rdma_update_sgid_attr(struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr *old_attr)
|
||||
{
|
||||
if (old_attr)
|
||||
rdma_put_gid_attr(old_attr);
|
||||
if (ah_attr->ah_flags & IB_AH_GRH) {
|
||||
rdma_hold_gid_attr(ah_attr->grh.sgid_attr);
|
||||
return ah_attr->grh.sgid_attr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
u32 flags,
|
||||
@@ -378,6 +524,7 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
|
||||
ah->device = device;
|
||||
ah->pd = pd;
|
||||
ah->type = ah_attr->type;
|
||||
ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
|
||||
|
||||
ret = device->create_ah(ah, ah_attr, flags, udata);
|
||||
if (ret) {
|
||||
@@ -403,10 +550,17 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
|
||||
struct ib_ah *rdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
|
||||
u32 flags)
|
||||
{
|
||||
const struct ib_gid_attr *old_sgid_attr;
|
||||
struct ib_ah *ah;
|
||||
int ret;
|
||||
|
||||
ret = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ah = _rdma_create_ah(pd, ah_attr, flags, NULL);
|
||||
|
||||
rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
|
||||
return ah;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_create_ah);
|
||||
@@ -429,15 +583,27 @@ struct ib_ah *rdma_create_user_ah(struct ib_pd *pd,
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
const struct ib_gid_attr *old_sgid_attr;
|
||||
struct ib_ah *ah;
|
||||
int err;
|
||||
|
||||
if (rdma_protocol_roce(pd->device, ah_attr->port_num)) {
|
||||
err = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
|
||||
err = ib_resolve_eth_dmac(pd->device, ah_attr);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
if (err) {
|
||||
ah = ERR_PTR(err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return _rdma_create_ah(pd, ah_attr, RDMA_CREATE_AH_SLEEPABLE, udata);
|
||||
ah = _rdma_create_ah(pd, ah_attr, RDMA_CREATE_AH_SLEEPABLE, udata);
|
||||
|
||||
out:
|
||||
rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
|
||||
return ah;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_user_ah);
|
||||
|
||||
@@ -528,16 +694,16 @@ static bool find_gid_index(const union ib_gid *gid,
|
||||
return (vlan_diff == 0x0000 || vlan_diff == 0xFFFF);
|
||||
}
|
||||
|
||||
static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
|
||||
u16 vlan_id, const union ib_gid *sgid,
|
||||
enum ib_gid_type gid_type,
|
||||
u16 *gid_index)
|
||||
static const struct ib_gid_attr *
|
||||
get_sgid_attr_from_eth(struct ib_device *device, u8 port_num,
|
||||
u16 vlan_id, const union ib_gid *sgid,
|
||||
enum ib_gid_type gid_type)
|
||||
{
|
||||
struct find_gid_index_context context = {.vlan_id = vlan_id,
|
||||
.gid_type = gid_type};
|
||||
|
||||
return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
|
||||
&context, gid_index);
|
||||
return rdma_find_gid_by_filter(device, sgid, port_num, find_gid_index,
|
||||
&context);
|
||||
}
|
||||
|
||||
int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
|
||||
@@ -581,39 +747,24 @@ EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
|
||||
static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
struct ib_gid_attr sgid_attr;
|
||||
struct ib_global_route *grh;
|
||||
struct ib_global_route *grh = rdma_ah_retrieve_grh(ah_attr);
|
||||
const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
|
||||
int hop_limit = 0xff;
|
||||
union ib_gid sgid;
|
||||
int ret;
|
||||
|
||||
grh = rdma_ah_retrieve_grh(ah_attr);
|
||||
|
||||
ret = ib_query_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;
|
||||
}
|
||||
int ret = 0;
|
||||
|
||||
/* If destination is link local and source GID is RoCEv1,
|
||||
* IP stack is not used.
|
||||
*/
|
||||
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,
|
||||
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,
|
||||
sgid_attr.ndev, &hop_limit);
|
||||
done:
|
||||
dev_put(sgid_attr.ndev);
|
||||
sgid_attr->ndev, &hop_limit);
|
||||
|
||||
grh->hop_limit = hop_limit;
|
||||
return ret;
|
||||
@@ -628,16 +779,18 @@ done:
|
||||
* as sgid and, sgid is used as dgid because sgid contains destinations
|
||||
* 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,
|
||||
const struct ib_wc *wc, const struct ib_grh *grh,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
u32 flow_class;
|
||||
u16 gid_index = 0;
|
||||
int ret;
|
||||
enum rdma_network_type net_type = RDMA_NETWORK_IB;
|
||||
enum ib_gid_type gid_type = IB_GID_TYPE_IB;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
int hoplimit = 0xff;
|
||||
union ib_gid dgid;
|
||||
union ib_gid sgid;
|
||||
@@ -666,70 +819,141 @@ int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
|
||||
if (!(wc->wc_flags & IB_WC_GRH))
|
||||
return -EPROTOTYPE;
|
||||
|
||||
ret = get_sgid_index_from_eth(device, port_num,
|
||||
vlan_id, &dgid,
|
||||
gid_type, &gid_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
sgid_attr = get_sgid_attr_from_eth(device, port_num,
|
||||
vlan_id, &dgid,
|
||||
gid_type);
|
||||
if (IS_ERR(sgid_attr))
|
||||
return PTR_ERR(sgid_attr);
|
||||
|
||||
flow_class = be32_to_cpu(grh->version_tclass_flow);
|
||||
rdma_ah_set_grh(ah_attr, &sgid,
|
||||
flow_class & 0xFFFFF,
|
||||
(u8)gid_index, hoplimit,
|
||||
(flow_class >> 20) & 0xFF);
|
||||
return ib_resolve_unicast_gid_dmac(device, ah_attr);
|
||||
rdma_move_grh_sgid_attr(ah_attr,
|
||||
&sgid,
|
||||
flow_class & 0xFFFFF,
|
||||
hoplimit,
|
||||
(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 {
|
||||
rdma_ah_set_dlid(ah_attr, wc->slid);
|
||||
rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);
|
||||
|
||||
if (wc->wc_flags & IB_WC_GRH) {
|
||||
if (dgid.global.interface_id != cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
|
||||
ret = ib_find_cached_gid_by_port(device, &dgid,
|
||||
IB_GID_TYPE_IB,
|
||||
port_num, NULL,
|
||||
&gid_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if ((wc->wc_flags & IB_WC_GRH) == 0)
|
||||
return 0;
|
||||
|
||||
flow_class = be32_to_cpu(grh->version_tclass_flow);
|
||||
rdma_ah_set_grh(ah_attr, &sgid,
|
||||
if (dgid.global.interface_id !=
|
||||
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,
|
||||
(u8)gid_index, hoplimit,
|
||||
(flow_class >> 20) & 0xFF);
|
||||
}
|
||||
hoplimit,
|
||||
(flow_class >> 20) & 0xFF,
|
||||
sgid_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ib_init_ah_attr_from_wc);
|
||||
|
||||
/**
|
||||
* rdma_move_grh_sgid_attr - Sets the sgid attribute of GRH, taking ownership
|
||||
* of the reference
|
||||
*
|
||||
* @attr: Pointer to AH attribute structure
|
||||
* @dgid: Destination GID
|
||||
* @flow_label: Flow label
|
||||
* @hop_limit: Hop limit
|
||||
* @traffic_class: traffic class
|
||||
* @sgid_attr: Pointer to SGID attribute
|
||||
*
|
||||
* This takes ownership of the sgid_attr reference. The caller must ensure
|
||||
* rdma_destroy_ah_attr() is called before destroying the rdma_ah_attr after
|
||||
* calling this function.
|
||||
*/
|
||||
void rdma_move_grh_sgid_attr(struct rdma_ah_attr *attr, union ib_gid *dgid,
|
||||
u32 flow_label, u8 hop_limit, u8 traffic_class,
|
||||
const struct ib_gid_attr *sgid_attr)
|
||||
{
|
||||
rdma_ah_set_grh(attr, dgid, flow_label, sgid_attr->index, hop_limit,
|
||||
traffic_class);
|
||||
attr->grh.sgid_attr = sgid_attr;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_move_grh_sgid_attr);
|
||||
|
||||
/**
|
||||
* rdma_destroy_ah_attr - Release reference to SGID attribute of
|
||||
* ah attribute.
|
||||
* @ah_attr: Pointer to ah attribute
|
||||
*
|
||||
* Release reference to the SGID attribute of the ah attribute if it is
|
||||
* non NULL. It is safe to call this multiple times, and safe to call it on
|
||||
* a zero initialized ah_attr.
|
||||
*/
|
||||
void rdma_destroy_ah_attr(struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
if (ah_attr->grh.sgid_attr) {
|
||||
rdma_put_gid_attr(ah_attr->grh.sgid_attr);
|
||||
ah_attr->grh.sgid_attr = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_destroy_ah_attr);
|
||||
|
||||
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)
|
||||
{
|
||||
struct rdma_ah_attr ah_attr;
|
||||
struct ib_ah *ah;
|
||||
int ret;
|
||||
|
||||
ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return rdma_create_ah(pd, &ah_attr, RDMA_CREATE_AH_SLEEPABLE);
|
||||
ah = rdma_create_ah(pd, &ah_attr, RDMA_CREATE_AH_SLEEPABLE);
|
||||
|
||||
rdma_destroy_ah_attr(&ah_attr);
|
||||
return ah;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_ah_from_wc);
|
||||
|
||||
int rdma_modify_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
const struct ib_gid_attr *old_sgid_attr;
|
||||
int ret;
|
||||
|
||||
if (ah->type != ah_attr->type)
|
||||
return -EINVAL;
|
||||
|
||||
return ah->device->modify_ah ?
|
||||
ret = rdma_fill_sgid_attr(ah->device, ah_attr, &old_sgid_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ah->device->modify_ah ?
|
||||
ah->device->modify_ah(ah, ah_attr) :
|
||||
-EOPNOTSUPP;
|
||||
|
||||
ah->sgid_attr = rdma_update_sgid_attr(ah_attr, ah->sgid_attr);
|
||||
rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_modify_ah);
|
||||
|
||||
int rdma_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
ah_attr->grh.sgid_attr = NULL;
|
||||
|
||||
return ah->device->query_ah ?
|
||||
ah->device->query_ah(ah, ah_attr) :
|
||||
-EOPNOTSUPP;
|
||||
@@ -738,6 +962,7 @@ EXPORT_SYMBOL(rdma_query_ah);
|
||||
|
||||
int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
|
||||
{
|
||||
const struct ib_gid_attr *sgid_attr = ah->sgid_attr;
|
||||
struct ib_pd *pd;
|
||||
|
||||
might_sleep_if(flags & RDMA_DESTROY_AH_SLEEPABLE);
|
||||
@@ -745,6 +970,8 @@ int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
|
||||
pd = ah->pd;
|
||||
ah->device->destroy_ah(ah, flags);
|
||||
atomic_dec(&pd->usecnt);
|
||||
if (sgid_attr)
|
||||
rdma_put_gid_attr(sgid_attr);
|
||||
|
||||
kfree(ah);
|
||||
return 0;
|
||||
@@ -1323,16 +1550,19 @@ bool ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_modify_qp_is_ok);
|
||||
|
||||
/**
|
||||
* ib_resolve_eth_dmac - Resolve destination mac address
|
||||
* @device: Device to consider
|
||||
* @ah_attr: address handle attribute which describes the
|
||||
* source and destination parameters
|
||||
* ib_resolve_eth_dmac() resolves destination mac address and L3 hop limit It
|
||||
* returns 0 on success or appropriate error code. It initializes the
|
||||
* necessary ah_attr fields when call is successful.
|
||||
*/
|
||||
static int ib_resolve_eth_dmac(struct ib_device *device,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ib_global_route *grh;
|
||||
|
||||
if (!rdma_is_port_valid(device, rdma_ah_get_port_num(ah_attr)))
|
||||
return -EINVAL;
|
||||
|
||||
grh = rdma_ah_retrieve_grh(ah_attr);
|
||||
int ret = 0;
|
||||
|
||||
if (rdma_is_multicast_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) {
|
||||
if (ipv6_addr_v4mapped((struct in6_addr *)ah_attr->grh.dgid.raw)) {
|
||||
@@ -1365,19 +1595,35 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
|
||||
int attr_mask, struct ib_udata *udata)
|
||||
{
|
||||
u8 port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
|
||||
const struct ib_gid_attr *old_sgid_attr_av;
|
||||
const struct ib_gid_attr *old_sgid_attr_alt_av;
|
||||
int ret;
|
||||
|
||||
if (port < rdma_start_port(qp->device) ||
|
||||
port > rdma_end_port(qp->device))
|
||||
return -EINVAL;
|
||||
|
||||
if (attr_mask & IB_QP_AV) {
|
||||
ret = rdma_fill_sgid_attr(qp->device, &attr->ah_attr,
|
||||
&old_sgid_attr_av);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (attr_mask & IB_QP_ALT_PATH) {
|
||||
/*
|
||||
* FIXME: This does not track the migration state, so if the
|
||||
* user loads a new alternate path after the HW has migrated
|
||||
* from primary->alternate we will keep the wrong
|
||||
* references. This is OK for IB because the reference
|
||||
* counting does not serve any functional purpose.
|
||||
*/
|
||||
ret = rdma_fill_sgid_attr(qp->device, &attr->alt_ah_attr,
|
||||
&old_sgid_attr_alt_av);
|
||||
if (ret)
|
||||
goto out_av;
|
||||
|
||||
/*
|
||||
* Today the core code can only handle alternate paths and APM
|
||||
* for IB. Ban them in roce mode.
|
||||
*/
|
||||
if (!(rdma_protocol_ib(qp->device,
|
||||
attr->alt_ah_attr.port_num) &&
|
||||
attr->alt_ah_attr.port_num) &&
|
||||
rdma_protocol_ib(qp->device, port))) {
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
@@ -1418,7 +1664,19 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
|
||||
|
||||
if (attr_mask & IB_QP_PORT)
|
||||
qp->port = attr->port_num;
|
||||
if (attr_mask & IB_QP_AV)
|
||||
qp->av_sgid_attr =
|
||||
rdma_update_sgid_attr(&attr->ah_attr, qp->av_sgid_attr);
|
||||
if (attr_mask & IB_QP_ALT_PATH)
|
||||
qp->alt_path_sgid_attr = rdma_update_sgid_attr(
|
||||
&attr->alt_ah_attr, qp->alt_path_sgid_attr);
|
||||
|
||||
out:
|
||||
if (attr_mask & IB_QP_ALT_PATH)
|
||||
rdma_unfill_sgid_attr(&attr->alt_ah_attr, old_sgid_attr_alt_av);
|
||||
out_av:
|
||||
if (attr_mask & IB_QP_AV)
|
||||
rdma_unfill_sgid_attr(&attr->ah_attr, old_sgid_attr_av);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1453,6 +1711,9 @@ int ib_query_qp(struct ib_qp *qp,
|
||||
int qp_attr_mask,
|
||||
struct ib_qp_init_attr *qp_init_attr)
|
||||
{
|
||||
qp_attr->ah_attr.grh.sgid_attr = NULL;
|
||||
qp_attr->alt_ah_attr.grh.sgid_attr = NULL;
|
||||
|
||||
return qp->device->query_qp ?
|
||||
qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
|
||||
-EOPNOTSUPP;
|
||||
@@ -1509,6 +1770,8 @@ static int __ib_destroy_shared_qp(struct ib_qp *qp)
|
||||
|
||||
int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
|
||||
{
|
||||
const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
|
||||
const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
|
||||
struct ib_pd *pd;
|
||||
struct ib_cq *scq, *rcq;
|
||||
struct ib_srq *srq;
|
||||
@@ -1529,6 +1792,10 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
|
||||
|
||||
ret = qp->device->destroy_qp(qp, udata);
|
||||
if (!ret) {
|
||||
if (alt_path_sgid_attr)
|
||||
rdma_put_gid_attr(alt_path_sgid_attr);
|
||||
if (av_sgid_attr)
|
||||
rdma_put_gid_attr(av_sgid_attr);
|
||||
if (pd)
|
||||
atomic_dec(&pd->usecnt);
|
||||
if (scq)
|
||||
@@ -2171,7 +2438,6 @@ static void __ib_drain_sq(struct ib_qp *qp)
|
||||
struct ib_cq *cq = qp->send_cq;
|
||||
struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
|
||||
struct ib_drain_cqe sdrain;
|
||||
const struct ib_send_wr *bad_swr;
|
||||
struct ib_rdma_wr swr = {
|
||||
.wr = {
|
||||
.opcode = IB_WR_RDMA_WRITE,
|
||||
@@ -2189,7 +2455,7 @@ static void __ib_drain_sq(struct ib_qp *qp)
|
||||
sdrain.cqe.done = ib_drain_qp_done;
|
||||
init_completion(&sdrain.done);
|
||||
|
||||
ret = ib_post_send(qp, &swr.wr, &bad_swr);
|
||||
ret = ib_post_send(qp, &swr.wr, NULL);
|
||||
if (ret) {
|
||||
WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
|
||||
return;
|
||||
@@ -2211,7 +2477,6 @@ static void __ib_drain_rq(struct ib_qp *qp)
|
||||
struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
|
||||
struct ib_drain_cqe rdrain;
|
||||
struct ib_recv_wr rwr = {};
|
||||
const struct ib_recv_wr *bad_rwr;
|
||||
int ret;
|
||||
|
||||
ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
|
||||
@@ -2224,7 +2489,7 @@ static void __ib_drain_rq(struct ib_qp *qp)
|
||||
rdrain.cqe.done = ib_drain_qp_done;
|
||||
init_completion(&rdrain.done);
|
||||
|
||||
ret = ib_post_recv(qp, &rwr, &bad_rwr);
|
||||
ret = ib_post_recv(qp, &rwr, NULL);
|
||||
if (ret) {
|
||||
WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
|
||||
return;
|
||||
|
||||
@@ -80,7 +80,7 @@ static struct ib_send_wr ipoib_cm_rx_drain_wr = {
|
||||
};
|
||||
|
||||
static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event);
|
||||
const struct ib_cm_event *event);
|
||||
|
||||
static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, struct ipoib_cm_rx_buf *rx_req)
|
||||
{
|
||||
@@ -91,7 +91,6 @@ static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, struct ipoib_cm_r
|
||||
|
||||
static int ipoib_cm_post_receive_srq(struct ipoib_dev_priv *priv, int id)
|
||||
{
|
||||
const struct ib_recv_wr *bad_wr;
|
||||
struct ipoib_rx_buf *rx_req;
|
||||
struct mbuf *m;
|
||||
int ret;
|
||||
@@ -106,7 +105,7 @@ static int ipoib_cm_post_receive_srq(struct ipoib_dev_priv *priv, int id)
|
||||
priv->cm.rx_wr.num_sge = i;
|
||||
priv->cm.rx_wr.wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV;
|
||||
|
||||
ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, &bad_wr);
|
||||
ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, NULL);
|
||||
if (unlikely(ret)) {
|
||||
ipoib_warn(priv, "post srq failed for buf %d (%d)\n", id, ret);
|
||||
ipoib_dma_unmap_rx(priv, rx_req);
|
||||
@@ -123,7 +122,6 @@ static int ipoib_cm_post_receive_nonsrq(struct ipoib_dev_priv *priv,
|
||||
struct ib_sge *sge, int id)
|
||||
{
|
||||
struct ipoib_rx_buf *rx_req;
|
||||
const struct ib_recv_wr *bad_wr;
|
||||
struct mbuf *m;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -137,7 +135,7 @@ static int ipoib_cm_post_receive_nonsrq(struct ipoib_dev_priv *priv,
|
||||
wr->num_sge = i;
|
||||
wr->wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV;
|
||||
|
||||
ret = ib_post_recv(rx->qp, wr, &bad_wr);
|
||||
ret = ib_post_recv(rx->qp, wr, NULL);
|
||||
if (unlikely(ret)) {
|
||||
ipoib_warn(priv, "post recv failed for buf %d (%d)\n", id, ret);
|
||||
ipoib_dma_unmap_rx(priv, rx_req);
|
||||
@@ -171,7 +169,6 @@ static void ipoib_cm_free_rx_ring(struct ipoib_dev_priv *priv,
|
||||
|
||||
static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv)
|
||||
{
|
||||
const struct ib_send_wr *bad_wr;
|
||||
struct ipoib_cm_rx *p;
|
||||
|
||||
/* We only reserved 1 extra slot in CQ for drain WRs, so
|
||||
@@ -185,7 +182,7 @@ static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv)
|
||||
* error" WC will be immediately generated for each WR we post.
|
||||
*/
|
||||
p = list_entry(priv->cm.rx_flush_list.next, typeof(*p), list);
|
||||
if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, &bad_wr))
|
||||
if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, NULL))
|
||||
ipoib_warn(priv, "failed to post drain wr\n");
|
||||
|
||||
list_splice_init(&priv->cm.rx_flush_list, &priv->cm.rx_drain_list);
|
||||
@@ -367,7 +364,8 @@ err_free:
|
||||
}
|
||||
|
||||
static int ipoib_cm_send_rep(struct ipoib_dev_priv *priv, struct ib_cm_id *cm_id,
|
||||
struct ib_qp *qp, struct ib_cm_req_event_param *req,
|
||||
struct ib_qp *qp,
|
||||
const struct ib_cm_req_event_param *req,
|
||||
unsigned psn)
|
||||
{
|
||||
struct ipoib_cm_data data = {};
|
||||
@@ -386,7 +384,8 @@ static int ipoib_cm_send_rep(struct ipoib_dev_priv *priv, struct ib_cm_id *cm_id
|
||||
return ib_send_cm_rep(cm_id, &rep);
|
||||
}
|
||||
|
||||
static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
|
||||
static int ipoib_cm_req_handler(struct ib_cm_id *cm_id,
|
||||
const struct ib_cm_event *event)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = cm_id->context;
|
||||
struct ipoib_cm_rx *p;
|
||||
@@ -447,7 +446,7 @@ err_qp:
|
||||
}
|
||||
|
||||
static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event)
|
||||
const struct ib_cm_event *event)
|
||||
{
|
||||
struct ipoib_cm_rx *p;
|
||||
struct ipoib_dev_priv *priv;
|
||||
@@ -595,7 +594,6 @@ static inline int post_send(struct ipoib_dev_priv *priv,
|
||||
struct ipoib_cm_tx_buf *tx_req,
|
||||
unsigned int wr_id)
|
||||
{
|
||||
const struct ib_send_wr *bad_wr;
|
||||
struct mbuf *mb = tx_req->mb;
|
||||
u64 *mapping = tx_req->mapping;
|
||||
struct mbuf *m;
|
||||
@@ -609,7 +607,7 @@ static inline int post_send(struct ipoib_dev_priv *priv,
|
||||
priv->tx_wr.wr.wr_id = wr_id | IPOIB_OP_CM;
|
||||
priv->tx_wr.wr.opcode = IB_WR_SEND;
|
||||
|
||||
return ib_post_send(tx->qp, &priv->tx_wr.wr, &bad_wr);
|
||||
return ib_post_send(tx->qp, &priv->tx_wr.wr, NULL);
|
||||
}
|
||||
|
||||
void ipoib_cm_send(struct ipoib_dev_priv *priv, struct mbuf *mb, struct ipoib_cm_tx *tx)
|
||||
@@ -839,7 +837,8 @@ void ipoib_cm_dev_stop(struct ipoib_dev_priv *priv)
|
||||
cancel_delayed_work_sync(&priv->cm.stale_task);
|
||||
}
|
||||
|
||||
static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
|
||||
static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id,
|
||||
const struct ib_cm_event *event)
|
||||
{
|
||||
struct ipoib_cm_tx *p = cm_id->context;
|
||||
struct ipoib_dev_priv *priv = p->priv;
|
||||
@@ -1105,7 +1104,7 @@ timeout:
|
||||
}
|
||||
|
||||
static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event)
|
||||
const struct ib_cm_event *event)
|
||||
{
|
||||
struct ipoib_cm_tx *tx = cm_id->context;
|
||||
struct ipoib_dev_priv *priv = tx->priv;
|
||||
|
||||
@@ -90,7 +90,7 @@ static int ipoib_set_coalesce(if_t dev,
|
||||
ret = rdma_set_cq_moderation(priv->recv_cq,
|
||||
coal->rx_max_coalesced_frames,
|
||||
coal->rx_coalesce_usecs);
|
||||
if (ret && ret != -ENOSYS) {
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@ error:
|
||||
static int ipoib_ib_post_receive(struct ipoib_dev_priv *priv, int id)
|
||||
{
|
||||
struct ipoib_rx_buf *rx_req;
|
||||
const struct ib_recv_wr *bad_wr;
|
||||
struct mbuf *m;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -163,7 +162,7 @@ static int ipoib_ib_post_receive(struct ipoib_dev_priv *priv, int id)
|
||||
priv->rx_wr.num_sge = i;
|
||||
priv->rx_wr.wr_id = id | IPOIB_OP_RECV;
|
||||
|
||||
ret = ib_post_recv(priv->qp, &priv->rx_wr, &bad_wr);
|
||||
ret = ib_post_recv(priv->qp, &priv->rx_wr, NULL);
|
||||
if (unlikely(ret)) {
|
||||
ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
|
||||
ipoib_dma_unmap_rx(priv, &priv->rx_ring[id]);
|
||||
@@ -453,7 +452,6 @@ post_send(struct ipoib_dev_priv *priv, unsigned int wr_id,
|
||||
struct ib_ah *address, u32 qpn, struct ipoib_tx_buf *tx_req, void *head,
|
||||
int hlen)
|
||||
{
|
||||
const struct ib_send_wr *bad_wr;
|
||||
struct mbuf *mb = tx_req->mb;
|
||||
u64 *mapping = tx_req->mapping;
|
||||
struct mbuf *m;
|
||||
@@ -476,7 +474,7 @@ post_send(struct ipoib_dev_priv *priv, unsigned int wr_id,
|
||||
} else
|
||||
priv->tx_wr.wr.opcode = IB_WR_SEND;
|
||||
|
||||
return ib_post_send(priv->qp, &priv->tx_wr.wr, &bad_wr);
|
||||
return ib_post_send(priv->qp, &priv->tx_wr.wr, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -531,8 +531,10 @@ path_rec_completion(int status, struct sa_path_rec *pathrec, void *path_ptr)
|
||||
struct rdma_ah_attr av;
|
||||
|
||||
if (!ib_init_ah_attr_from_path(priv->ca, priv->port,
|
||||
pathrec, &av))
|
||||
pathrec, &av, NULL)) {
|
||||
ah = ipoib_create_ah(priv, priv->pd, &av);
|
||||
rdma_destroy_ah_attr(&av);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
@@ -1012,9 +1014,9 @@ ipoib_add_port(const char *format, struct ib_device *hca, u8 port)
|
||||
priv->broadcastaddr[8] = priv->pkey >> 8;
|
||||
priv->broadcastaddr[9] = priv->pkey & 0xff;
|
||||
|
||||
result = ib_query_gid(hca, port, 0, &priv->local_gid, NULL);
|
||||
result = rdma_query_gid(hca, port, 0, &priv->local_gid);
|
||||
if (result) {
|
||||
printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n",
|
||||
printk(KERN_WARNING "%s: rdma_query_gid port %d failed (ret = %d)\n",
|
||||
hca->name, port, result);
|
||||
goto device_init_failed;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/completion.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
|
||||
static int mcast_debug_level = 1;
|
||||
@@ -484,8 +485,8 @@ void ipoib_mcast_join_task(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid, NULL))
|
||||
ipoib_warn(priv, "ib_query_gid() failed\n");
|
||||
if (rdma_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
|
||||
ipoib_warn(priv, "rdma_query_gid() failed\n");
|
||||
else
|
||||
memcpy(if_getlladdr(dev) + 4, priv->local_gid.raw, sizeof (union ib_gid));
|
||||
|
||||
|
||||
@@ -61,12 +61,12 @@ struct ib_addr {
|
||||
#define sib_interface_id ib_u.uib_addr64[1]
|
||||
};
|
||||
|
||||
static inline int ib_addr_any(const struct ib_addr *a)
|
||||
static inline bool ib_addr_any(const struct ib_addr *a)
|
||||
{
|
||||
return ((a->sib_addr64[0] | a->sib_addr64[1]) == 0);
|
||||
}
|
||||
|
||||
static inline int ib_addr_loopback(const struct ib_addr *a)
|
||||
static inline bool ib_addr_loopback(const struct ib_addr *a)
|
||||
{
|
||||
return ((a->sib_addr32[0] | a->sib_addr32[1] |
|
||||
a->sib_addr32[2] | (a->sib_addr32[3] ^ htonl(1))) == 0);
|
||||
|
||||
@@ -72,6 +72,7 @@ union rdma_sockaddr {
|
||||
* @bound_dev_if: An optional device interface index.
|
||||
* @transport: The transport type used.
|
||||
* @net: Network namespace containing the bound_dev_if net_dev.
|
||||
* @sgid_attr: GID attribute to use for identified SGID
|
||||
*/
|
||||
struct vnet;
|
||||
struct rdma_dev_addr {
|
||||
@@ -82,6 +83,7 @@ struct rdma_dev_addr {
|
||||
int bound_dev_if;
|
||||
enum rdma_transport_type transport;
|
||||
struct vnet *net;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
enum rdma_network_type network;
|
||||
int hoplimit;
|
||||
};
|
||||
@@ -110,7 +112,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
|
||||
* or been canceled. A status of 0 indicates success.
|
||||
* @context: User-specified context associated with the call.
|
||||
*/
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr, int timeout_ms,
|
||||
void (*callback)(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *addr, void *context),
|
||||
@@ -122,7 +124,7 @@ void rdma_copy_addr(struct rdma_dev_addr *dev_addr,
|
||||
const if_t dev,
|
||||
const unsigned char *dst_dev_addr);
|
||||
|
||||
int rdma_addr_size(struct sockaddr *addr);
|
||||
int rdma_addr_size(const struct sockaddr *addr);
|
||||
int rdma_addr_size_in6(struct sockaddr_in6 *addr);
|
||||
int rdma_addr_size_kss(struct sockaddr_storage *addr);
|
||||
|
||||
|
||||
@@ -39,45 +39,23 @@
|
||||
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
/**
|
||||
* ib_get_cached_gid - Returns a cached GID table entry
|
||||
* @device: The device to query.
|
||||
* @port_num: The port number of the device to query.
|
||||
* @index: The index into the cached GID table to query.
|
||||
* @gid: The GID value found at the specified index.
|
||||
* @attr: The GID attribute found at the specified index (only in RoCE).
|
||||
* NULL means ignore (output parameter).
|
||||
*
|
||||
* ib_get_cached_gid() fetches the specified GID table entry stored in
|
||||
* the local software cache.
|
||||
*/
|
||||
int ib_get_cached_gid(struct ib_device *device,
|
||||
u8 port_num,
|
||||
int index,
|
||||
union ib_gid *gid,
|
||||
struct ib_gid_attr *attr);
|
||||
int rdma_query_gid(struct ib_device *device, u8 port_num, int index,
|
||||
union ib_gid *gid);
|
||||
const struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
if_t ndev);
|
||||
const struct ib_gid_attr *rdma_find_gid_by_port(struct ib_device *ib_dev,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
u8 port,
|
||||
if_t ndev);
|
||||
const struct ib_gid_attr *rdma_find_gid_by_filter(
|
||||
struct ib_device *device, const union ib_gid *gid, u8 port_num,
|
||||
bool (*filter)(const union ib_gid *gid, const struct ib_gid_attr *,
|
||||
void *),
|
||||
void *context);
|
||||
|
||||
int ib_find_cached_gid(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
if_t ndev,
|
||||
u8 *port_num,
|
||||
u16 *index);
|
||||
|
||||
int ib_find_cached_gid_by_port(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
u8 port_num,
|
||||
if_t ndev,
|
||||
u16 *index);
|
||||
|
||||
int ib_find_gid_by_filter(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
u8 port_num,
|
||||
bool (*filter)(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *,
|
||||
void *),
|
||||
void *context, u16 *index);
|
||||
/**
|
||||
* ib_get_cached_pkey - Returns a cached PKey table entry
|
||||
* @device: The device to query.
|
||||
@@ -152,4 +130,8 @@ int ib_get_cached_port_state(struct ib_device *device,
|
||||
enum ib_port_state *port_active);
|
||||
|
||||
bool rdma_is_zero_gid(const union ib_gid *gid);
|
||||
const struct ib_gid_attr *rdma_get_gid_attr(struct ib_device *device,
|
||||
u8 port_num, int index);
|
||||
void rdma_put_gid_attr(const struct ib_gid_attr *attr);
|
||||
void rdma_hold_gid_attr(const struct ib_gid_attr *attr);
|
||||
#endif /* _IB_CACHE_H */
|
||||
@@ -124,11 +124,11 @@ struct ib_cm_req_event_param {
|
||||
struct sa_path_rec *alternate_path;
|
||||
|
||||
/*
|
||||
* SGID index of the primary path. Currently only
|
||||
* SGID attribute of the primary path. Currently only
|
||||
* useful for RoCE. Alternate path GID attributes
|
||||
* are not yet supported.
|
||||
*/
|
||||
u8 ppath_sgid_index;
|
||||
const struct ib_gid_attr *ppath_sgid_attr;
|
||||
|
||||
__be64 remote_ca_guid;
|
||||
u32 remote_qkey;
|
||||
@@ -238,11 +238,10 @@ struct ib_cm_sidr_req_event_param {
|
||||
__be64 service_id;
|
||||
|
||||
/*
|
||||
* SGID index of the request. Currently only
|
||||
* SGID attribute of the request. Currently only
|
||||
* useful for RoCE.
|
||||
*/
|
||||
u8 sgid_index;
|
||||
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
/* P_Key that was used by the GMP's BTH header */
|
||||
u16 bth_pkey;
|
||||
u8 port;
|
||||
@@ -263,6 +262,7 @@ struct ib_cm_sidr_rep_event_param {
|
||||
u32 qkey;
|
||||
u32 qpn;
|
||||
void *info;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
u8 info_len;
|
||||
};
|
||||
|
||||
@@ -314,7 +314,7 @@ struct ib_cm_event {
|
||||
* destroy the @cm_id after the callback completes.
|
||||
*/
|
||||
typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event);
|
||||
const struct ib_cm_event *event);
|
||||
|
||||
struct ib_cm_id {
|
||||
ib_cm_handler cm_handler;
|
||||
@@ -382,6 +382,7 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
|
||||
struct ib_cm_req_param {
|
||||
struct sa_path_rec *primary_path;
|
||||
struct sa_path_rec *alternate_path;
|
||||
const struct ib_gid_attr *ppath_sgid_attr;
|
||||
__be64 service_id;
|
||||
u32 qp_num;
|
||||
enum ib_qp_type qp_type;
|
||||
@@ -583,6 +584,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
|
||||
|
||||
struct ib_cm_sidr_req_param {
|
||||
struct sa_path_rec *path;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
__be64 service_id;
|
||||
int timeout_ms;
|
||||
const void *private_data;
|
||||
|
||||
@@ -173,12 +173,7 @@ struct sa_path_rec_ib {
|
||||
*/
|
||||
struct sa_path_rec_roce {
|
||||
bool route_resolved;
|
||||
u8 dmac[ETH_ALEN];
|
||||
/* ignored in IB */
|
||||
int ifindex;
|
||||
/* ignored in IB */
|
||||
struct vnet *net;
|
||||
|
||||
u8 dmac[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct sa_path_rec_opa {
|
||||
@@ -557,13 +552,10 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
|
||||
enum ib_gid_type gid_type,
|
||||
struct rdma_ah_attr *ah_attr);
|
||||
|
||||
/**
|
||||
* ib_init_ah_attr_from_path - Initialize address handle attributes based on
|
||||
* an SA path record.
|
||||
*/
|
||||
int ib_init_ah_attr_from_path(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec,
|
||||
struct rdma_ah_attr *ah_attr);
|
||||
struct rdma_ah_attr *ah_attr,
|
||||
const struct ib_gid_attr *sgid_attr);
|
||||
|
||||
/**
|
||||
* ib_sa_pack_path - Conert a path record from struct ib_sa_path_rec
|
||||
@@ -668,45 +660,10 @@ static inline void sa_path_set_dmac_zero(struct sa_path_rec *rec)
|
||||
eth_zero_addr(rec->roce.dmac);
|
||||
}
|
||||
|
||||
static inline void sa_path_set_ifindex(struct sa_path_rec *rec, int ifindex)
|
||||
{
|
||||
if (sa_path_is_roce(rec))
|
||||
rec->roce.ifindex = ifindex;
|
||||
}
|
||||
|
||||
static inline void sa_path_set_ndev(struct sa_path_rec *rec, struct vnet *net)
|
||||
{
|
||||
if (sa_path_is_roce(rec))
|
||||
rec->roce.net = net;
|
||||
}
|
||||
|
||||
static inline u8 *sa_path_get_dmac(struct sa_path_rec *rec)
|
||||
{
|
||||
if (sa_path_is_roce(rec))
|
||||
return rec->roce.dmac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int sa_path_get_ifindex(struct sa_path_rec *rec)
|
||||
{
|
||||
if (sa_path_is_roce(rec))
|
||||
return rec->roce.ifindex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct vnet *sa_path_get_ndev(struct sa_path_rec *rec)
|
||||
{
|
||||
if (sa_path_is_roce(rec))
|
||||
return rec->roce.net;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline if_t ib_get_ndev_from_path(struct sa_path_rec *rec)
|
||||
{
|
||||
return sa_path_get_ndev(rec) ?
|
||||
dev_get_by_index(sa_path_get_ndev(rec),
|
||||
sa_path_get_ifindex(rec))
|
||||
: NULL;
|
||||
}
|
||||
|
||||
#endif /* IB_SA_H */
|
||||
@@ -122,7 +122,8 @@ typedef int (*umem_call_back)(struct ib_umem *item, u64 start, u64 end,
|
||||
*/
|
||||
int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
|
||||
u64 start, u64 end,
|
||||
umem_call_back cb, void *cookie);
|
||||
umem_call_back cb,
|
||||
bool blockable, void *cookie);
|
||||
|
||||
/*
|
||||
* Find first region intersecting with address range.
|
||||
|
||||
@@ -105,6 +105,7 @@ enum ib_gid_type {
|
||||
struct ib_gid_attr {
|
||||
if_t ndev;
|
||||
struct ib_device *device;
|
||||
union ib_gid gid;
|
||||
enum ib_gid_type gid_type;
|
||||
u16 index;
|
||||
u8 port_num;
|
||||
@@ -159,13 +160,13 @@ static inline enum ib_gid_type ib_network_to_gid_type(enum rdma_network_type net
|
||||
return IB_GID_TYPE_IB;
|
||||
}
|
||||
|
||||
static inline enum rdma_network_type ib_gid_to_network_type(enum ib_gid_type gid_type,
|
||||
union ib_gid *gid)
|
||||
static inline enum rdma_network_type
|
||||
rdma_gid_attr_network_type(const struct ib_gid_attr *attr)
|
||||
{
|
||||
if (gid_type == IB_GID_TYPE_IB)
|
||||
if (attr->gid_type == IB_GID_TYPE_IB)
|
||||
return RDMA_NETWORK_IB;
|
||||
|
||||
if (ipv6_addr_v4mapped((struct in6_addr *)gid))
|
||||
if (ipv6_addr_v4mapped((const struct in6_addr *)&attr->gid))
|
||||
return RDMA_NETWORK_IPV4;
|
||||
else
|
||||
return RDMA_NETWORK_IPV6;
|
||||
@@ -709,6 +710,7 @@ struct ib_event_handler {
|
||||
} while (0)
|
||||
|
||||
struct ib_global_route {
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
union ib_gid dgid;
|
||||
u32 flow_label;
|
||||
u8 sgid_index;
|
||||
@@ -1498,6 +1500,7 @@ struct ib_ah {
|
||||
struct ib_device *device;
|
||||
struct ib_pd *pd;
|
||||
struct ib_uobject *uobject;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
enum rdma_ah_attr_type type;
|
||||
};
|
||||
|
||||
@@ -1643,6 +1646,9 @@ struct ib_qp {
|
||||
struct ib_uqp_object *uobject;
|
||||
void (*event_handler)(struct ib_event *, void *);
|
||||
void *qp_context;
|
||||
/* sgid_attrs associated with the AV's */
|
||||
const struct ib_gid_attr *av_sgid_attr;
|
||||
const struct ib_gid_attr *alt_path_sgid_attr;
|
||||
u32 qp_num;
|
||||
u32 max_write_sge;
|
||||
u32 max_read_sge;
|
||||
@@ -2204,8 +2210,7 @@ struct ib_device {
|
||||
* concurrently for different ports. This function is only called when
|
||||
* roce_gid_table is used.
|
||||
*/
|
||||
int (*add_gid)(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
int (*add_gid)(const struct ib_gid_attr *attr,
|
||||
void **context);
|
||||
/* When calling del_gid, the HW vendor's driver should delete the
|
||||
* gid of device @device at gid index gid_index of port port_num
|
||||
@@ -2937,10 +2942,6 @@ static inline bool rdma_cap_read_inv(struct ib_device *dev, u32 port_num)
|
||||
return rdma_protocol_iwarp(dev, port_num);
|
||||
}
|
||||
|
||||
int ib_query_gid(struct ib_device *device,
|
||||
u8 port_num, int index, union ib_gid *gid,
|
||||
struct ib_gid_attr *attr);
|
||||
|
||||
int ib_set_vf_link_state(struct ib_device *device, int vf, u8 port,
|
||||
int state);
|
||||
int ib_get_vf_config(struct ib_device *device, int vf, u8 port,
|
||||
@@ -3064,6 +3065,13 @@ int ib_get_rdma_header_version(const union rdma_network_hdr *hdr);
|
||||
* ignored unless the work completion indicates that the GRH is valid.
|
||||
* @ah_attr: Returned attributes that can be used when creating an address
|
||||
* 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,
|
||||
const struct ib_wc *wc, const struct ib_grh *grh,
|
||||
@@ -3197,7 +3205,9 @@ static inline int ib_post_srq_recv(struct ib_srq *srq,
|
||||
const struct ib_recv_wr *recv_wr,
|
||||
const struct ib_recv_wr **bad_recv_wr)
|
||||
{
|
||||
return srq->device->post_srq_recv(srq, recv_wr, bad_recv_wr);
|
||||
const struct ib_recv_wr *dummy;
|
||||
|
||||
return srq->device->post_srq_recv(srq, recv_wr, bad_recv_wr ? : &dummy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3310,7 +3320,9 @@ static inline int ib_post_send(struct ib_qp *qp,
|
||||
const struct ib_send_wr *send_wr,
|
||||
const struct ib_send_wr **bad_send_wr)
|
||||
{
|
||||
return qp->device->post_send(qp, send_wr, bad_send_wr);
|
||||
const struct ib_send_wr *dummy;
|
||||
|
||||
return qp->device->post_send(qp, send_wr, bad_send_wr ? : &dummy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3325,7 +3337,9 @@ static inline int ib_post_recv(struct ib_qp *qp,
|
||||
const struct ib_recv_wr *recv_wr,
|
||||
const struct ib_recv_wr **bad_recv_wr)
|
||||
{
|
||||
return qp->device->post_recv(qp, recv_wr, bad_recv_wr);
|
||||
const struct ib_recv_wr *dummy;
|
||||
|
||||
return qp->device->post_recv(qp, recv_wr, bad_recv_wr ? : &dummy);
|
||||
}
|
||||
|
||||
struct ib_cq *__ib_alloc_cq_user(struct ib_device *dev, void *private,
|
||||
@@ -4094,8 +4108,19 @@ static inline void rdma_ah_set_grh(struct rdma_ah_attr *attr,
|
||||
grh->sgid_index = sgid_index;
|
||||
grh->hop_limit = hop_limit;
|
||||
grh->traffic_class = traffic_class;
|
||||
grh->sgid_attr = NULL;
|
||||
}
|
||||
|
||||
void rdma_destroy_ah_attr(struct rdma_ah_attr *ah_attr);
|
||||
void rdma_move_grh_sgid_attr(struct rdma_ah_attr *attr, union ib_gid *dgid,
|
||||
u32 flow_label, u8 hop_limit, u8 traffic_class,
|
||||
const struct ib_gid_attr *sgid_attr);
|
||||
void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
|
||||
const struct rdma_ah_attr *src);
|
||||
void rdma_replace_ah_attr(struct rdma_ah_attr *old,
|
||||
const struct rdma_ah_attr *new);
|
||||
void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src);
|
||||
|
||||
/**
|
||||
* rdma_ah_find_type - Return address handle type.
|
||||
*
|
||||
|
||||
@@ -119,7 +119,7 @@ static inline bool rdma_is_valid_unicast_lid(struct rdma_ah_attr *attr)
|
||||
if (attr->type == RDMA_AH_ATTR_TYPE_IB) {
|
||||
if (!rdma_ah_get_dlid(attr) ||
|
||||
rdma_ah_get_dlid(attr) >=
|
||||
be32_to_cpu(IB_MULTICAST_LID_BASE))
|
||||
be16_to_cpu(IB_MULTICAST_LID_BASE))
|
||||
return false;
|
||||
} else if (attr->type == RDMA_AH_ATTR_TYPE_OPA) {
|
||||
if (!rdma_ah_get_dlid(attr) ||
|
||||
|
||||
@@ -196,7 +196,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
|
||||
* @timeout_ms: Time to wait for resolution to complete.
|
||||
*/
|
||||
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr, int timeout_ms);
|
||||
const struct sockaddr *dst_addr, int timeout_ms);
|
||||
|
||||
/**
|
||||
* rdma_resolve_route - Resolve the RDMA address bound to the RDMA identifier
|
||||
|
||||
Reference in new issue
Block a user