RDMA/cxgb3: Streaming -> RDMA mode transition fixes
authorSteve Wise <swise@opengridcomputing.com>
Mon, 14 May 2007 18:27:27 +0000 (13:27 -0500)
committerRoland Dreier <rolandd@cisco.com>
Tue, 10 Jul 2007 03:12:26 +0000 (20:12 -0700)
Due to a HW issue, our current scheme to transition the connection from
streaming to rdma mode is broken on the passive side.  The firmware
and driver now support a new transition scheme for the passive side:

 - driver posts rdma_init_wr (now including the initial receive seqno)
 - driver posts last streaming message via TX_DATA message (MPA start
   response)
 - uP atomically sends the last streaming message and transitions the
   tcb to rdma mode.
 - driver waits for wr_ack indicating the last streaming message was ACKed.

NOTE: This change also bumps the required firmware version to 4.3.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_cm.h
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/net/cxgb3/version.h

index 76049afc76554ef2a4c0487b348faca768dfc3d7..215bbe51047a3f760959a5837c8d17331b61ad69 100644 (file)
@@ -833,7 +833,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
        wqe->ird = cpu_to_be32(attr->ird);
        wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
        wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
-       wqe->rsvd = 0;
+       wqe->irs = cpu_to_be32(attr->irs);
        skb->priority = 0;      /* 0=>ToeQ; 1=>CtrlQ */
        return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
 }
index ff7290eacefb7ee83ec95565384a29891a06f91b..c84d4ac49355b3bc2f3d41f265b4e75c8cb568cf 100644 (file)
@@ -294,6 +294,7 @@ struct t3_rdma_init_attr {
        u64 qp_dma_addr;
        u32 qp_dma_size;
        u32 flags;
+       u32 irs;
 };
 
 struct t3_rdma_init_wr {
@@ -314,7 +315,7 @@ struct t3_rdma_init_wr {
        __be32 ird;
        __be64 qp_dma_addr;     /* 7 */
        __be32 qp_dma_size;     /* 8 */
-       u32 rsvd;
+       u32 irs;
 };
 
 struct t3_genbit {
index b2faff5abce8648f533211fec884d0fc04b8d19d..7b8d5aaa220441c5e4ec7ecd89dc743e20836db2 100644 (file)
@@ -515,7 +515,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        BUG_ON(ep->mpa_skb);
        ep->mpa_skb = skb;
@@ -566,7 +566,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
        req->len = htonl(mpalen);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        BUG_ON(ep->mpa_skb);
        ep->mpa_skb = skb;
@@ -618,7 +618,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
                           V_TX_SNDBUF(snd_win>>15));
-       req->flags = htonl(F_TX_MORE | F_TX_IMM_ACK | F_TX_INIT);
+       req->flags = htonl(F_TX_INIT);
        req->sndseq = htonl(ep->snd_seq);
        ep->mpa_skb = skb;
        state_set(&ep->com, MPA_REP_SENT);
@@ -641,6 +641,7 @@ static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        cxgb3_insert_tid(ep->com.tdev, &t3c_client, ep, tid);
 
        ep->snd_seq = ntohl(req->snd_isn);
+       ep->rcv_seq = ntohl(req->rcv_isn);
 
        set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1023,6 +1024,9 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        skb_pull(skb, sizeof(*hdr));
        skb_trim(skb, dlen);
 
+       ep->rcv_seq += dlen;
+       BUG_ON(ep->rcv_seq != (ntohl(hdr->seq) + dlen));
+
        switch (state_read(&ep->com)) {
        case MPA_REQ_SENT:
                process_mpa_reply(ep, skb);
@@ -1060,7 +1064,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        struct iwch_ep *ep = ctx;
        struct cpl_wr_ack *hdr = cplhdr(skb);
        unsigned int credits = ntohs(hdr->credits);
-       enum iwch_qp_attr_mask  mask;
 
        PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
 
@@ -1072,30 +1075,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        ep->mpa_skb = NULL;
        dst_confirm(ep->dst);
        if (state_read(&ep->com) == MPA_REP_SENT) {
-               struct iwch_qp_attributes attrs;
-
-               /* bind QP to EP and move to RTS */
-               attrs.mpa_attr = ep->mpa_attr;
-               attrs.max_ird = ep->ord;
-               attrs.max_ord = ep->ord;
-               attrs.llp_stream_handle = ep;
-               attrs.next_state = IWCH_QP_STATE_RTS;
-
-               /* bind QP and TID with INIT_WR */
-               mask = IWCH_QP_ATTR_NEXT_STATE |
-                                    IWCH_QP_ATTR_LLP_STREAM_HANDLE |
-                                    IWCH_QP_ATTR_MPA_ATTR |
-                                    IWCH_QP_ATTR_MAX_IRD |
-                                    IWCH_QP_ATTR_MAX_ORD;
-
-               ep->com.rpl_err = iwch_modify_qp(ep->com.qp->rhp,
-                                    ep->com.qp, mask, &attrs, 1);
-
-               if (!ep->com.rpl_err) {
-                       state_set(&ep->com, FPDU_MODE);
-                       established_upcall(ep);
-               }
-
                ep->com.rpl_done = 1;
                PDBG("waking up ep %p\n", ep);
                wake_up(&ep->com.waitq);
@@ -1378,6 +1357,7 @@ static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 
        PDBG("%s ep %p\n", __FUNCTION__, ep);
        ep->snd_seq = ntohl(req->snd_isn);
+       ep->rcv_seq = ntohl(req->rcv_isn);
 
        set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1732,10 +1712,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
 
        PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
-       if (state_read(&ep->com) == DEAD) {
-               put_ep(&ep->com);
+       if (state_read(&ep->com) == DEAD)
                return -ECONNRESET;
-       }
 
        BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
        BUG_ON(!qp);
@@ -1755,17 +1733,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        ep->ird = conn_param->ird;
        ep->ord = conn_param->ord;
        PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
+
        get_ep(&ep->com);
-       err = send_mpa_reply(ep, conn_param->private_data,
-                            conn_param->private_data_len);
-       if (err) {
-               ep->com.cm_id = NULL;
-               ep->com.qp = NULL;
-               cm_id->rem_ref(cm_id);
-               abort_connection(ep, NULL, GFP_KERNEL);
-               put_ep(&ep->com);
-               return err;
-       }
 
        /* bind QP to EP and move to RTS */
        attrs.mpa_attr = ep->mpa_attr;
@@ -1783,16 +1752,29 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
        err = iwch_modify_qp(ep->com.qp->rhp,
                             ep->com.qp, mask, &attrs, 1);
+       if (err)
+               goto err;
 
-       if (err) {
-               ep->com.cm_id = NULL;
-               ep->com.qp = NULL;
-               cm_id->rem_ref(cm_id);
-               abort_connection(ep, NULL, GFP_KERNEL);
-       } else {
-               state_set(&ep->com, FPDU_MODE);
-               established_upcall(ep);
-       }
+       err = send_mpa_reply(ep, conn_param->private_data,
+                            conn_param->private_data_len);
+       if (err)
+               goto err;
+
+       /* wait for wr_ack */
+       wait_event(ep->com.waitq, ep->com.rpl_done);
+       err = ep->com.rpl_err;
+       if (err)
+               goto err;
+
+       state_set(&ep->com, FPDU_MODE);
+       established_upcall(ep);
+       put_ep(&ep->com);
+       return 0;
+err:
+       ep->com.cm_id = NULL;
+       ep->com.qp = NULL;
+       cm_id->rem_ref(cm_id);
+       abort_connection(ep, NULL, GFP_KERNEL);
        put_ep(&ep->com);
        return err;
 }
index 21a388c313cffb536a2812fbc54a054480bd73f9..6107e7cd9b57dd54377c29601a473bbd8f24cc12 100644 (file)
@@ -175,6 +175,7 @@ struct iwch_ep {
        unsigned int atid;
        u32 hwtid;
        u32 snd_seq;
+       u32 rcv_seq;
        struct l2t_entry *l2t;
        struct dst_entry *dst;
        struct sk_buff *mpa_skb;
index 714dddbc9a987ec3ba6ac7633226d1e1cd831e1b..679b7c179273d8dbee618a4636c094b3214e6037 100644 (file)
@@ -732,6 +732,7 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
        init_attr.qp_dma_addr = qhp->wq.dma_addr;
        init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
        init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+       init_attr.irs = qhp->ep->rcv_seq;
        PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
             "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
             init_attr.rq_addr, init_attr.rq_size,
index 8eddd23a3a51c077cfd922870acc179d97e06c6a..eb508bf8022a0595bd228b2ede3e94040e39f782 100644 (file)
@@ -39,6 +39,6 @@
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 1
+#define FW_VERSION_MINOR 3
 #define FW_VERSION_MICRO 0
 #endif                         /* __CHELSIO_VERSION_H */