Skip to content

Commit d2ca39f

Browse files
Yossi EtiginRoland Dreier
authored andcommitted
RDMA/cma: Create cm id even when IB port is down
When doing rdma_resolve_addr(), if the relevant IB port is down, the function fails and the cm_id is not bound to the correct device. Therefore, application does not have a device handle and cannot wait for the port to become active. The function fails because the underlying IPoIB interface is not joined to the broadcast group and therefore the SA does not have a multicast record to take a Q_Key from. The fix is to use lazy Q_Key resolution - cma_set_qkey() will set id_priv->qkey if it was not set, and will be called just before the Q_Key is really required. Signed-off-by: Yossi Etigin <yosefe@voltaire.com> Acked-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
1 parent 84adeee commit d2ca39f

File tree

1 file changed

+27
-14
lines changed
  • drivers/infiniband/core

1 file changed

+27
-14
lines changed

drivers/infiniband/core/cma.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -297,21 +297,25 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv)
297297
id_priv->cma_dev = NULL;
298298
}
299299

300-
static int cma_set_qkey(struct ib_device *device, u8 port_num,
301-
enum rdma_port_space ps,
302-
struct rdma_dev_addr *dev_addr, u32 *qkey)
300+
static int cma_set_qkey(struct rdma_id_private *id_priv)
303301
{
304302
struct ib_sa_mcmember_rec rec;
305303
int ret = 0;
306304

307-
switch (ps) {
305+
if (id_priv->qkey)
306+
return 0;
307+
308+
switch (id_priv->id.ps) {
308309
case RDMA_PS_UDP:
309-
*qkey = RDMA_UDP_QKEY;
310+
id_priv->qkey = RDMA_UDP_QKEY;
310311
break;
311312
case RDMA_PS_IPOIB:
312-
ib_addr_get_mgid(dev_addr, &rec.mgid);
313-
ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec);
314-
*qkey = be32_to_cpu(rec.qkey);
313+
ib_addr_get_mgid(&id_priv->id.route.addr.dev_addr, &rec.mgid);
314+
ret = ib_sa_get_mcmember_rec(id_priv->id.device,
315+
id_priv->id.port_num, &rec.mgid,
316+
&rec);
317+
if (!ret)
318+
id_priv->qkey = be32_to_cpu(rec.qkey);
315319
break;
316320
default:
317321
break;
@@ -341,12 +345,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
341345
ret = ib_find_cached_gid(cma_dev->device, &gid,
342346
&id_priv->id.port_num, NULL);
343347
if (!ret) {
344-
ret = cma_set_qkey(cma_dev->device,
345-
id_priv->id.port_num,
346-
id_priv->id.ps, dev_addr,
347-
&id_priv->qkey);
348-
if (!ret)
349-
cma_attach_to_dev(id_priv, cma_dev);
348+
cma_attach_to_dev(id_priv, cma_dev);
350349
break;
351350
}
352351
}
@@ -578,6 +577,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
578577
*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
579578

580579
if (cma_is_ud_ps(id_priv->id.ps)) {
580+
ret = cma_set_qkey(id_priv);
581+
if (ret)
582+
return ret;
583+
581584
qp_attr->qkey = id_priv->qkey;
582585
*qp_attr_mask |= IB_QP_QKEY;
583586
} else {
@@ -2201,6 +2204,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
22012204
event.status = ib_event->param.sidr_rep_rcvd.status;
22022205
break;
22032206
}
2207+
ret = cma_set_qkey(id_priv);
2208+
if (ret) {
2209+
event.event = RDMA_CM_EVENT_ADDR_ERROR;
2210+
event.status = -EINVAL;
2211+
break;
2212+
}
22042213
if (id_priv->qkey != rep->qkey) {
22052214
event.event = RDMA_CM_EVENT_UNREACHABLE;
22062215
event.status = -EINVAL;
@@ -2480,10 +2489,14 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
24802489
const void *private_data, int private_data_len)
24812490
{
24822491
struct ib_cm_sidr_rep_param rep;
2492+
int ret;
24832493

24842494
memset(&rep, 0, sizeof rep);
24852495
rep.status = status;
24862496
if (status == IB_SIDR_SUCCESS) {
2497+
ret = cma_set_qkey(id_priv);
2498+
if (ret)
2499+
return ret;
24872500
rep.qp_num = id_priv->qp_num;
24882501
rep.qkey = id_priv->qkey;
24892502
}

0 commit comments

Comments
 (0)