Commit 80783868 authored by Steve Wise's avatar Steve Wise Committed by Roland Dreier

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: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 257313b2
...@@ -913,7 +913,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb) ...@@ -913,7 +913,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
goto err; goto err;
if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) { if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
iwch_post_zb_read(ep->com.qp); iwch_post_zb_read(ep);
} }
goto out; goto out;
...@@ -1077,6 +1077,8 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) ...@@ -1077,6 +1077,8 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *ep = ctx; struct iwch_ep *ep = ctx;
struct cpl_wr_ack *hdr = cplhdr(skb); struct cpl_wr_ack *hdr = cplhdr(skb);
unsigned int credits = ntohs(hdr->credits); unsigned int credits = ntohs(hdr->credits);
unsigned long flags;
int post_zb = 0;
PDBG("%s ep %p credits %u\n", __func__, ep, credits); 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) ...@@ -1086,28 +1088,34 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
return CPL_RET_BUF_DONE; return CPL_RET_BUF_DONE;
} }
spin_lock_irqsave(&ep->com.lock, flags);
BUG_ON(credits != 1); BUG_ON(credits != 1);
dst_confirm(ep->dst); dst_confirm(ep->dst);
if (!ep->mpa_skb) { if (!ep->mpa_skb) {
PDBG("%s rdma_init wr_ack ep %p state %u\n", 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) { if (ep->mpa_attr.initiator) {
PDBG("%s initiator ep %p state %u\n", PDBG("%s initiator ep %p state %u\n",
__func__, ep, state_read(&ep->com)); __func__, ep, ep->com.state);
if (peer2peer) if (peer2peer && ep->com.state == FPDU_MODE)
iwch_post_zb_read(ep->com.qp); post_zb = 1;
} else { } else {
PDBG("%s responder ep %p state %u\n", PDBG("%s responder ep %p state %u\n",
__func__, ep, state_read(&ep->com)); __func__, ep, ep->com.state);
ep->com.rpl_done = 1; if (ep->com.state == MPA_REQ_RCVD) {
wake_up(&ep->com.waitq); ep->com.rpl_done = 1;
wake_up(&ep->com.waitq);
}
} }
} else { } else {
PDBG("%s lsm ack ep %p state %u freeing skb\n", 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); kfree_skb(ep->mpa_skb);
ep->mpa_skb = NULL; ep->mpa_skb = NULL;
} }
spin_unlock_irqrestore(&ep->com.lock, flags);
if (post_zb)
iwch_post_zb_read(ep);
return CPL_RET_BUF_DONE; return CPL_RET_BUF_DONE;
} }
......
...@@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp, ...@@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp,
struct ib_mw_bind *mw_bind); struct ib_mw_bind *mw_bind);
int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); 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_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); int iwch_register_device(struct iwch_dev *dev);
void iwch_unregister_device(struct iwch_dev *dev); void iwch_unregister_device(struct iwch_dev *dev);
void stop_read_rep_timer(struct iwch_qp *qhp); void stop_read_rep_timer(struct iwch_qp *qhp);
......
...@@ -738,7 +738,7 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg, ...@@ -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; union t3_wr *wqe;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_qp *qhp) ...@@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_qp *qhp)
wqe->read.local_len = cpu_to_be32(0); wqe->read.local_len = cpu_to_be32(0);
wqe->read.local_to = cpu_to_be64(1); 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.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)); V_FW_RIWR_LEN(flit_cnt));
skb->priority = CPL_PRIORITY_DATA; 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);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment