diff options
author | np <np@FreeBSD.org> | 2017-03-23 17:11:34 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2017-03-23 17:11:34 +0000 |
commit | f24a7358bb426010bbbec51cd16ec87daabf1e17 (patch) | |
tree | 41606e42ba436e0b52224ba52b0172c15dd86dbe /sys/dev/cxgbe | |
parent | ac845c230b7df4f889bae9dd2b42725afa53581b (diff) | |
download | FreeBSD-src-f24a7358bb426010bbbec51cd16ec87daabf1e17.zip FreeBSD-src-f24a7358bb426010bbbec51cd16ec87daabf1e17.tar.gz |
MFC r314814 and r315325.
r314814:
cxgbe/iw_cxgbe: Abort connection if there is an error during c4iw_modify_qp.
r315325:
cxgbe/iw_cxgbe: Use the socket and not the toepcb to reach for the
inpcb. t4_tom detaches the inpcb from the toepcb as soon as the
hardware is done with the connection (in final_cpl_received) but the
socket is around as long as the cm_id and the rest of iWARP state is.
This fixes an intermittent NULL dereference during abort.
Diffstat (limited to 'sys/dev/cxgbe')
-rw-r--r-- | sys/dev/cxgbe/iw_cxgbe/qp.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/sys/dev/cxgbe/iw_cxgbe/qp.c b/sys/dev/cxgbe/iw_cxgbe/qp.c index 58a89c5..3bc1a96 100644 --- a/sys/dev/cxgbe/iw_cxgbe/qp.c +++ b/sys/dev/cxgbe/iw_cxgbe/qp.c @@ -64,7 +64,7 @@ struct cpl_set_tcb_rpl; #include "iw_cxgbe.h" #include "user.h" -static void creds(struct toepcb *toep, size_t wrsize); +static int creds(struct toepcb *toep, struct inpcb *inp, size_t wrsize); static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state) @@ -961,6 +961,7 @@ static inline void build_term_codes(struct t4_cqe *err_cqe, u8 *layer_type, static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe, gfp_t gfp) { + int ret; struct fw_ri_wr *wqe; struct terminate_message *term; struct wrqe *wr; @@ -991,7 +992,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe, term->ecode = qhp->attr.ecode; } else build_term_codes(err_cqe, &term->layer_etype, &term->ecode); - creds(toep, sizeof(*wqe)); + ret = creds(toep, inp, sizeof(*wqe)); + if (ret) { + free_wrqe(wr); + return; + } t4_wrq_tx(qhp->rhp->rdev.adap, wr); } @@ -1094,7 +1099,11 @@ rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, struct c4iw_ep *ep) c4iw_init_wr_wait(&ep->com.wr_wait); - creds(toep, sizeof(*wqe)); + ret = creds(toep, inp, sizeof(*wqe)); + if (ret) { + free_wrqe(wr); + return ret; + } t4_wrq_tx(sc, wr); ret = c4iw_wait_for_reply(rdev, &ep->com.wr_wait, ep->hwtid, @@ -1127,13 +1136,17 @@ static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init) } } -static void -creds(struct toepcb *toep, size_t wrsize) +static int +creds(struct toepcb *toep, struct inpcb *inp, size_t wrsize) { struct ofld_tx_sdesc *txsd; CTR3(KTR_IW_CXGBE, "%s:creB %p %u", __func__, toep , wrsize); - INP_WLOCK(toep->inp); + INP_WLOCK(inp); + if ((inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT)) != 0) { + INP_WUNLOCK(inp); + return (EINVAL); + } txsd = &toep->txsd[toep->txsd_pidx]; txsd->tx_credits = howmany(wrsize, 16); txsd->plen = 0; @@ -1143,9 +1156,10 @@ creds(struct toepcb *toep, size_t wrsize) if (__predict_false(++toep->txsd_pidx == toep->txsd_total)) toep->txsd_pidx = 0; toep->txsd_avail--; - INP_WUNLOCK(toep->inp); + INP_WUNLOCK(inp); CTR5(KTR_IW_CXGBE, "%s:creE %p %u %u %u", __func__, toep , txsd->tx_credits, toep->tx_credits, toep->txsd_pidx); + return (0); } static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp) @@ -1216,7 +1230,11 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp) c4iw_init_wr_wait(&ep->com.wr_wait); - creds(toep, sizeof(*wqe)); + ret = creds(toep, inp, sizeof(*wqe)); + if (ret) { + free_wrqe(wr); + return ret; + } t4_wrq_tx(sc, wr); ret = c4iw_wait_for_reply(rdev, &ep->com.wr_wait, ep->hwtid, @@ -1427,6 +1445,7 @@ err: qhp->ep = NULL; set_state(qhp, C4IW_QP_STATE_ERROR); free = 1; + abort = 1; BUG_ON(!ep); flush_qp(qhp); wake_up(&qhp->wait); |