]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
RDMA/cxgb3: Don't post zero-byte read if endpoint is going away
authorSteve Wise <swise@opengridcomputing.com>
Fri, 13 May 2011 18:37:18 +0000 (18:37 +0000)
committerRoland Dreier <roland@purestorage.com>
Tue, 24 May 2011 17:01:04 +0000 (10:01 -0700)
tx_ack() wasn't checking the endpoint state and consequently would
attempt to post the p2p 0B read on an endpoint/QP that is closing or
aborting.  This causes a NULL pointer dereference crash.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_provider.h
drivers/infiniband/hw/cxgb3/iwch_qp.c

index 3216bcad7e820088f3cf3d27b7feb14b62630c7e..ad998c0b51e259e09a65ffef5c783b7380bea554 100644 (file)
@@ -913,7 +913,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
                goto err;
 
        if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
-               iwch_post_zb_read(ep->com.qp);
+               iwch_post_zb_read(ep);
        }
 
        goto out;
@@ -1077,6 +1077,8 @@ 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);
+       unsigned long flags;
+       int post_zb = 0;
 
        PDBG("%s ep %p credits %u\n", __func__, ep, credits);
 
@@ -1086,28 +1088,34 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                return CPL_RET_BUF_DONE;
        }
 
+       spin_lock_irqsave(&ep->com.lock, flags);
        BUG_ON(credits != 1);
        dst_confirm(ep->dst);
        if (!ep->mpa_skb) {
                PDBG("%s rdma_init wr_ack ep %p state %u\n",
-                       __func__, ep, state_read(&ep->com));
+                       __func__, ep, ep->com.state);
                if (ep->mpa_attr.initiator) {
                        PDBG("%s initiator ep %p state %u\n",
-                               __func__, ep, state_read(&ep->com));
-                       if (peer2peer)
-                               iwch_post_zb_read(ep->com.qp);
+                               __func__, ep, ep->com.state);
+                       if (peer2peer && ep->com.state == FPDU_MODE)
+                               post_zb = 1;
                } else {
                        PDBG("%s responder ep %p state %u\n",
-                               __func__, ep, state_read(&ep->com));
-                       ep->com.rpl_done = 1;
-                       wake_up(&ep->com.waitq);
+                               __func__, ep, ep->com.state);
+                       if (ep->com.state == MPA_REQ_RCVD) {
+                               ep->com.rpl_done = 1;
+                               wake_up(&ep->com.waitq);
+                       }
                }
        } else {
                PDBG("%s lsm ack ep %p state %u freeing skb\n",
-                       __func__, ep, state_read(&ep->com));
+                       __func__, ep, ep->com.state);
                kfree_skb(ep->mpa_skb);
                ep->mpa_skb = NULL;
        }
+       spin_unlock_irqrestore(&ep->com.lock, flags);
+       if (post_zb)
+               iwch_post_zb_read(ep);
        return CPL_RET_BUF_DONE;
 }
 
index c5406da3f4cd2d28dc02e7480d6a4c224516095c..9a342c9b220d240afebce55e5abfac6f67ee4953 100644 (file)
@@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp,
                             struct ib_mw_bind *mw_bind);
 int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
 int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
-int iwch_post_zb_read(struct iwch_qp *qhp);
+int iwch_post_zb_read(struct iwch_ep *ep);
 int iwch_register_device(struct iwch_dev *dev);
 void iwch_unregister_device(struct iwch_dev *dev);
 void stop_read_rep_timer(struct iwch_qp *qhp);
index 1b4cd09f74dc2517567d8595fdd416c13ddd4941..ecd313f359a45ac6d90c0184ae1ccea3eeda7a6c 100644 (file)
@@ -738,7 +738,7 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
        }
 }
 
-int iwch_post_zb_read(struct iwch_qp *qhp)
+int iwch_post_zb_read(struct iwch_ep *ep)
 {
        union t3_wr *wqe;
        struct sk_buff *skb;
@@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_qp *qhp)
        wqe->read.local_len = cpu_to_be32(0);
        wqe->read.local_to = cpu_to_be64(1);
        wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
-       wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)|
+       wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(ep->hwtid)|
                                                V_FW_RIWR_LEN(flit_cnt));
        skb->priority = CPL_PRIORITY_DATA;
-       return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
+       return iwch_cxgb3_ofld_send(ep->com.qp->rhp->rdev.t3cdev_p, skb);
 }
 
 /*