aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2011-05-13 14:37:18 -0400
committerRoland Dreier <roland@purestorage.com>2011-05-24 13:01:04 -0400
commit807838686eb9e40d73b8a3f2384881358f51fff0 (patch)
tree13ab2b82122044054693e949513500bbc8967aef /drivers/infiniband
parent257313b2a87795e07a0bdf58d0fffbdba8b31051 (diff)
RDMA/cxgb3: Don't post zero-byte read if endpoint is going away
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>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c26
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h2
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c6
3 files changed, 21 insertions, 13 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 3216bcad7e82..ad998c0b51e2 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -913,7 +913,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
913 goto err; 913 goto err;
914 914
915 if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) { 915 if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
916 iwch_post_zb_read(ep->com.qp); 916 iwch_post_zb_read(ep);
917 } 917 }
918 918
919 goto out; 919 goto out;
@@ -1077,6 +1077,8 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1077 struct iwch_ep *ep = ctx; 1077 struct iwch_ep *ep = ctx;
1078 struct cpl_wr_ack *hdr = cplhdr(skb); 1078 struct cpl_wr_ack *hdr = cplhdr(skb);
1079 unsigned int credits = ntohs(hdr->credits); 1079 unsigned int credits = ntohs(hdr->credits);
1080 unsigned long flags;
1081 int post_zb = 0;
1080 1082
1081 PDBG("%s ep %p credits %u\n", __func__, ep, credits); 1083 PDBG("%s ep %p credits %u\n", __func__, ep, credits);
1082 1084
@@ -1086,28 +1088,34 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1086 return CPL_RET_BUF_DONE; 1088 return CPL_RET_BUF_DONE;
1087 } 1089 }
1088 1090
1091 spin_lock_irqsave(&ep->com.lock, flags);
1089 BUG_ON(credits != 1); 1092 BUG_ON(credits != 1);
1090 dst_confirm(ep->dst); 1093 dst_confirm(ep->dst);
1091 if (!ep->mpa_skb) { 1094 if (!ep->mpa_skb) {
1092 PDBG("%s rdma_init wr_ack ep %p state %u\n", 1095 PDBG("%s rdma_init wr_ack ep %p state %u\n",
1093 __func__, ep, state_read(&ep->com)); 1096 __func__, ep, ep->com.state);
1094 if (ep->mpa_attr.initiator) { 1097 if (ep->mpa_attr.initiator) {
1095 PDBG("%s initiator ep %p state %u\n", 1098 PDBG("%s initiator ep %p state %u\n",
1096 __func__, ep, state_read(&ep->com)); 1099 __func__, ep, ep->com.state);
1097 if (peer2peer) 1100 if (peer2peer && ep->com.state == FPDU_MODE)
1098 iwch_post_zb_read(ep->com.qp); 1101 post_zb = 1;
1099 } else { 1102 } else {
1100 PDBG("%s responder ep %p state %u\n", 1103 PDBG("%s responder ep %p state %u\n",
1101 __func__, ep, state_read(&ep->com)); 1104 __func__, ep, ep->com.state);
1102 ep->com.rpl_done = 1; 1105 if (ep->com.state == MPA_REQ_RCVD) {
1103 wake_up(&ep->com.waitq); 1106 ep->com.rpl_done = 1;
1107 wake_up(&ep->com.waitq);
1108 }
1104 } 1109 }
1105 } else { 1110 } else {
1106 PDBG("%s lsm ack ep %p state %u freeing skb\n", 1111 PDBG("%s lsm ack ep %p state %u freeing skb\n",
1107 __func__, ep, state_read(&ep->com)); 1112 __func__, ep, ep->com.state);
1108 kfree_skb(ep->mpa_skb); 1113 kfree_skb(ep->mpa_skb);
1109 ep->mpa_skb = NULL; 1114 ep->mpa_skb = NULL;
1110 } 1115 }
1116 spin_unlock_irqrestore(&ep->com.lock, flags);
1117 if (post_zb)
1118 iwch_post_zb_read(ep);
1111 return CPL_RET_BUF_DONE; 1119 return CPL_RET_BUF_DONE;
1112} 1120}
1113 1121
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index c5406da3f4cd..9a342c9b220d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp,
332 struct ib_mw_bind *mw_bind); 332 struct ib_mw_bind *mw_bind);
333int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); 333int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
334int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg); 334int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
335int iwch_post_zb_read(struct iwch_qp *qhp); 335int iwch_post_zb_read(struct iwch_ep *ep);
336int iwch_register_device(struct iwch_dev *dev); 336int iwch_register_device(struct iwch_dev *dev);
337void iwch_unregister_device(struct iwch_dev *dev); 337void iwch_unregister_device(struct iwch_dev *dev);
338void stop_read_rep_timer(struct iwch_qp *qhp); 338void stop_read_rep_timer(struct iwch_qp *qhp);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 1b4cd09f74dc..ecd313f359a4 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -738,7 +738,7 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
738 } 738 }
739} 739}
740 740
741int iwch_post_zb_read(struct iwch_qp *qhp) 741int iwch_post_zb_read(struct iwch_ep *ep)
742{ 742{
743 union t3_wr *wqe; 743 union t3_wr *wqe;
744 struct sk_buff *skb; 744 struct sk_buff *skb;
@@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_qp *qhp)
761 wqe->read.local_len = cpu_to_be32(0); 761 wqe->read.local_len = cpu_to_be32(0);
762 wqe->read.local_to = cpu_to_be64(1); 762 wqe->read.local_to = cpu_to_be64(1);
763 wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ)); 763 wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
764 wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)| 764 wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(ep->hwtid)|
765 V_FW_RIWR_LEN(flit_cnt)); 765 V_FW_RIWR_LEN(flit_cnt));
766 skb->priority = CPL_PRIORITY_DATA; 766 skb->priority = CPL_PRIORITY_DATA;
767 return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb); 767 return iwch_cxgb3_ofld_send(ep->com.qp->rhp->rdev.t3cdev_p, skb);
768} 768}
769 769
770/* 770/*