Commit d2ca39f2 authored by Yossi Etigin's avatar Yossi Etigin Committed by Roland Dreier

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: default avatarYossi Etigin <yosefe@voltaire.com>
Acked-by: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 84adeee9
...@@ -297,21 +297,25 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv) ...@@ -297,21 +297,25 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv)
id_priv->cma_dev = NULL; id_priv->cma_dev = NULL;
} }
static int cma_set_qkey(struct ib_device *device, u8 port_num, static int cma_set_qkey(struct rdma_id_private *id_priv)
enum rdma_port_space ps,
struct rdma_dev_addr *dev_addr, u32 *qkey)
{ {
struct ib_sa_mcmember_rec rec; struct ib_sa_mcmember_rec rec;
int ret = 0; int ret = 0;
switch (ps) { if (id_priv->qkey)
return 0;
switch (id_priv->id.ps) {
case RDMA_PS_UDP: case RDMA_PS_UDP:
*qkey = RDMA_UDP_QKEY; id_priv->qkey = RDMA_UDP_QKEY;
break; break;
case RDMA_PS_IPOIB: case RDMA_PS_IPOIB:
ib_addr_get_mgid(dev_addr, &rec.mgid); ib_addr_get_mgid(&id_priv->id.route.addr.dev_addr, &rec.mgid);
ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec); ret = ib_sa_get_mcmember_rec(id_priv->id.device,
*qkey = be32_to_cpu(rec.qkey); id_priv->id.port_num, &rec.mgid,
&rec);
if (!ret)
id_priv->qkey = be32_to_cpu(rec.qkey);
break; break;
default: default:
break; break;
...@@ -341,12 +345,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) ...@@ -341,12 +345,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
ret = ib_find_cached_gid(cma_dev->device, &gid, ret = ib_find_cached_gid(cma_dev->device, &gid,
&id_priv->id.port_num, NULL); &id_priv->id.port_num, NULL);
if (!ret) { if (!ret) {
ret = cma_set_qkey(cma_dev->device, cma_attach_to_dev(id_priv, cma_dev);
id_priv->id.port_num,
id_priv->id.ps, dev_addr,
&id_priv->qkey);
if (!ret)
cma_attach_to_dev(id_priv, cma_dev);
break; break;
} }
} }
...@@ -578,6 +577,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv, ...@@ -578,6 +577,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT; *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
if (cma_is_ud_ps(id_priv->id.ps)) { if (cma_is_ud_ps(id_priv->id.ps)) {
ret = cma_set_qkey(id_priv);
if (ret)
return ret;
qp_attr->qkey = id_priv->qkey; qp_attr->qkey = id_priv->qkey;
*qp_attr_mask |= IB_QP_QKEY; *qp_attr_mask |= IB_QP_QKEY;
} else { } else {
...@@ -2201,6 +2204,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, ...@@ -2201,6 +2204,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
event.status = ib_event->param.sidr_rep_rcvd.status; event.status = ib_event->param.sidr_rep_rcvd.status;
break; break;
} }
ret = cma_set_qkey(id_priv);
if (ret) {
event.event = RDMA_CM_EVENT_ADDR_ERROR;
event.status = -EINVAL;
break;
}
if (id_priv->qkey != rep->qkey) { if (id_priv->qkey != rep->qkey) {
event.event = RDMA_CM_EVENT_UNREACHABLE; event.event = RDMA_CM_EVENT_UNREACHABLE;
event.status = -EINVAL; event.status = -EINVAL;
...@@ -2480,10 +2489,14 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv, ...@@ -2480,10 +2489,14 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
const void *private_data, int private_data_len) const void *private_data, int private_data_len)
{ {
struct ib_cm_sidr_rep_param rep; struct ib_cm_sidr_rep_param rep;
int ret;
memset(&rep, 0, sizeof rep); memset(&rep, 0, sizeof rep);
rep.status = status; rep.status = status;
if (status == IB_SIDR_SUCCESS) { if (status == IB_SIDR_SUCCESS) {
ret = cma_set_qkey(id_priv);
if (ret)
return ret;
rep.qp_num = id_priv->qp_num; rep.qp_num = id_priv->qp_num;
rep.qkey = id_priv->qkey; rep.qkey = id_priv->qkey;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment