Skip to content

Commit 0fe313b

Browse files
Sean HeftyRoland Dreier
authored andcommitted
RDMA/cma: Allow early transition to RTS to handle lost CM messages
During connection establishment, the passive side of a connection can receive messages from the active side before the connection event has been delivered to the user. Allow the passive side to send messages in response to received data before the event is delivered. To handle the case where the connection messages are lost, a new rdma_notify() function is added that users may invoke to force a connection into the established state. Signed-off-by: Sean Hefty <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent a1b1b61 commit 0fe313b

File tree

3 files changed

+63
-24
lines changed

3 files changed

+63
-24
lines changed

drivers/infiniband/core/cm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,6 +3289,10 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
32893289

32903290
spin_lock_irqsave(&cm_id_priv->lock, flags);
32913291
switch (cm_id_priv->id.state) {
3292+
/* Allow transition to RTS before sending REP */
3293+
case IB_CM_REQ_RCVD:
3294+
case IB_CM_MRA_REQ_SENT:
3295+
32923296
case IB_CM_REP_RCVD:
32933297
case IB_CM_MRA_REP_SENT:
32943298
case IB_CM_REP_SENT:

drivers/infiniband/core/cma.c

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -760,22 +760,6 @@ static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
760760
return 0;
761761
}
762762

763-
static int cma_rtu_recv(struct rdma_id_private *id_priv)
764-
{
765-
int ret;
766-
767-
ret = cma_modify_qp_rts(&id_priv->id);
768-
if (ret)
769-
goto reject;
770-
771-
return 0;
772-
reject:
773-
cma_modify_qp_err(&id_priv->id);
774-
ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
775-
NULL, 0, NULL, 0);
776-
return ret;
777-
}
778-
779763
static void cma_set_rep_event_data(struct rdma_cm_event *event,
780764
struct ib_cm_rep_event_param *rep_data,
781765
void *private_data)
@@ -821,9 +805,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
821805
ib_event->private_data);
822806
break;
823807
case IB_CM_RTU_RECEIVED:
824-
event.status = cma_rtu_recv(id_priv);
825-
event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
826-
RDMA_CM_EVENT_ESTABLISHED;
808+
case IB_CM_USER_ESTABLISHED:
809+
event.event = RDMA_CM_EVENT_ESTABLISHED;
827810
break;
828811
case IB_CM_DREQ_ERROR:
829812
event.status = -ETIMEDOUT; /* fall through */
@@ -1989,11 +1972,25 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
19891972
struct rdma_conn_param *conn_param)
19901973
{
19911974
struct ib_cm_rep_param rep;
1992-
int ret;
1975+
struct ib_qp_attr qp_attr;
1976+
int qp_attr_mask, ret;
19931977

1994-
ret = cma_modify_qp_rtr(&id_priv->id);
1995-
if (ret)
1996-
return ret;
1978+
if (id_priv->id.qp) {
1979+
ret = cma_modify_qp_rtr(&id_priv->id);
1980+
if (ret)
1981+
goto out;
1982+
1983+
qp_attr.qp_state = IB_QPS_RTS;
1984+
ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
1985+
&qp_attr_mask);
1986+
if (ret)
1987+
goto out;
1988+
1989+
qp_attr.max_rd_atomic = conn_param->initiator_depth;
1990+
ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
1991+
if (ret)
1992+
goto out;
1993+
}
19971994

19981995
memset(&rep, 0, sizeof rep);
19991996
rep.qp_num = id_priv->qp_num;
@@ -2008,7 +2005,9 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
20082005
rep.rnr_retry_count = conn_param->rnr_retry_count;
20092006
rep.srq = id_priv->srq ? 1 : 0;
20102007

2011-
return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
2008+
ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
2009+
out:
2010+
return ret;
20122011
}
20132012

20142013
static int cma_accept_iw(struct rdma_id_private *id_priv,
@@ -2073,6 +2072,27 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
20732072
}
20742073
EXPORT_SYMBOL(rdma_accept);
20752074

2075+
int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
2076+
{
2077+
struct rdma_id_private *id_priv;
2078+
int ret;
2079+
2080+
id_priv = container_of(id, struct rdma_id_private, id);
2081+
if (!cma_comp(id_priv, CMA_CONNECT))
2082+
return -EINVAL;
2083+
2084+
switch (id->device->node_type) {
2085+
case RDMA_NODE_IB_CA:
2086+
ret = ib_cm_notify(id_priv->cm_id.ib, event);
2087+
break;
2088+
default:
2089+
ret = 0;
2090+
break;
2091+
}
2092+
return ret;
2093+
}
2094+
EXPORT_SYMBOL(rdma_notify);
2095+
20762096
int rdma_reject(struct rdma_cm_id *id, const void *private_data,
20772097
u8 private_data_len)
20782098
{

include/rdma/rdma_cm.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,21 @@ int rdma_listen(struct rdma_cm_id *id, int backlog);
252252
*/
253253
int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
254254

255+
/**
256+
* rdma_notify - Notifies the RDMA CM of an asynchronous event that has
257+
* occurred on the connection.
258+
* @id: Connection identifier to transition to established.
259+
* @event: Asynchronous event.
260+
*
261+
* This routine should be invoked by users to notify the CM of relevant
262+
* communication events. Events that should be reported to the CM and
263+
* when to report them are:
264+
*
265+
* IB_EVENT_COMM_EST - Used when a message is received on a connected
266+
* QP before an RTU has been received.
267+
*/
268+
int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event);
269+
255270
/**
256271
* rdma_reject - Called to reject a connection request or response.
257272
*/

0 commit comments

Comments
 (0)