From: Sean Hefty <[EMAIL PROTECTED]>

Allow ULPs to transition to RTS before sending a REP.  This allows the
ULP to respond to a received message if it arrives before the RTU or
communication established event.

Modify the RDMA CM to transition to RTS when sending a REP over IB, and
expose a new rdma_establish interface that a user can invoke to force a
connection into the established state if it polls a receive completion
before an RTU arrives.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>
---
Please consider for 2.6.19, since it does allow a connection to be made
when data is received on a QP, but the RTU is lost.  This problem has been
reported on the OFA OFED releases.

diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 25b1018..22ec434 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3243,6 +3243,10 @@ static int cm_init_qp_rts_attr(struct cm
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
        switch (cm_id_priv->id.state) {
+       /* Allow transition to RTS before sending REP */
+       case IB_CM_REQ_RCVD:
+       case IB_CM_MRA_REQ_SENT:
+
        case IB_CM_REP_RCVD:
        case IB_CM_MRA_REP_SENT:
        case IB_CM_REP_SENT:
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 9ae4f3a..bc20662 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -775,22 +775,6 @@ static int cma_verify_rep(struct rdma_id
        return 0;
 }
 
-static int cma_rtu_recv(struct rdma_id_private *id_priv)
-{
-       int ret;
-
-       ret = cma_modify_qp_rts(&id_priv->id);
-       if (ret)
-               goto reject;
-
-       return 0;
-reject:
-       cma_modify_qp_err(&id_priv->id);
-       ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
-                      NULL, 0, NULL, 0);
-       return ret;
-}
-
 static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
        struct rdma_id_private *id_priv = cm_id->context;
@@ -821,9 +805,8 @@ static int cma_ib_handler(struct ib_cm_i
                private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
                break;
        case IB_CM_RTU_RECEIVED:
-               status = cma_rtu_recv(id_priv);
-               event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
-                                RDMA_CM_EVENT_ESTABLISHED;
+       case IB_CM_USER_ESTABLISHED:
+               event = RDMA_CM_EVENT_ESTABLISHED;
                break;
        case IB_CM_DREQ_ERROR:
                status = -ETIMEDOUT; /* fall through */
@@ -1960,11 +1943,25 @@ static int cma_accept_ib(struct rdma_id_
                         struct rdma_conn_param *conn_param)
 {
        struct ib_cm_rep_param rep;
-       int ret;
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
 
-       ret = cma_modify_qp_rtr(&id_priv->id);
-       if (ret)
-               return ret;
+       if (id_priv->id.qp) {
+               ret = cma_modify_qp_rtr(&id_priv->id);
+               if (ret)
+                       goto out;
+
+               qp_attr.qp_state = IB_QPS_RTS;
+               ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
+                                        &qp_attr_mask);
+               if (ret)
+                       goto out;
+
+               qp_attr.max_rd_atomic = conn_param->initiator_depth;
+               ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+               if (ret)
+                       goto out;
+       }
 
        memset(&rep, 0, sizeof rep);
        rep.qp_num = id_priv->qp_num;
@@ -1979,7 +1976,9 @@ static int cma_accept_ib(struct rdma_id_
        rep.rnr_retry_count = conn_param->rnr_retry_count;
        rep.srq = id_priv->srq ? 1 : 0;
 
-       return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+       ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+out:
+       return ret;
 }
 
 static int cma_accept_iw(struct rdma_id_private *id_priv,
@@ -2045,6 +2044,27 @@ reject:
 }
 EXPORT_SYMBOL(rdma_accept);
 
+int rdma_establish(struct rdma_cm_id *id)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               return -EINVAL;
+
+       switch (id->device->node_type) {
+       case RDMA_NODE_IB_CA:
+               ret = ib_cm_establish(id_priv->cm_id.ib);
+               break;
+       default:
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_establish);
+
 int rdma_reject(struct rdma_cm_id *id, const void *private_data,
                u8 private_data_len)
 {
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index deb5a0a..2460881 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -253,6 +253,16 @@ int rdma_listen(struct rdma_cm_id *id, i
 int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
 
 /**
+ * rdma_establish - Forces a connection state to established.
+ * @id: Connection identifier to transition to established.
+ *
+ * This routine should be invoked by users who receive messages on a
+ * QP before being notified that the connection has been established by the
+ * RDMA CM.
+ */
+int rdma_establish(struct rdma_cm_id *id);
+
+/**
  * rdma_reject - Called to reject a connection request or response.
  */
 int rdma_reject(struct rdma_cm_id *id, const void *private_data,


_______________________________________________
openib-general mailing list
openib-general@openib.org
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to