summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgbe/tom/t4_listen.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cxgbe/tom/t4_listen.c')
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c102
1 files changed, 47 insertions, 55 deletions
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index 84cd1a2..e5c457d 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -282,8 +282,8 @@ send_reset_synqe(struct toedev *tod, struct synq_entry *synqe)
INP_WLOCK_ASSERT(synqe->lctx->inp);
- CTR4(KTR_CXGBE, "%s: synqe %p, tid %d%s",
- __func__, synqe, synqe->tid,
+ CTR5(KTR_CXGBE, "%s: synqe %p (0x%x), tid %d%s",
+ __func__, synqe, synqe->flags, synqe->tid,
synqe->flags & TPF_ABORT_SHUTDOWN ?
" (abort already in progress)" : "");
if (synqe->flags & TPF_ABORT_SHUTDOWN)
@@ -501,8 +501,10 @@ t4_listen_stop(struct toedev *tod, struct tcpcb *tp)
* socket's so_comp. It doesn't know about the connections on the synq
* so we need to take care of those.
*/
- TAILQ_FOREACH(synqe, &lctx->synq, link)
- send_reset_synqe(tod, synqe);
+ TAILQ_FOREACH(synqe, &lctx->synq, link) {
+ if (synqe->flags & TPF_SYNQE_HAS_L2TE)
+ send_reset_synqe(tod, synqe);
+ }
destroy_server(sc, lctx);
return (0);
@@ -1131,8 +1133,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
synqe->lctx = lctx;
synqe->syn = m;
m = NULL;
- refcount_init(&synqe->refcnt, 1); /* 1 so that it is held for the
- duration of this function */
+ refcount_init(&synqe->refcnt, 0);
synqe->l2e_idx = e->idx;
synqe->rcv_bufsize = rx_credits;
atomic_store_rel_ptr(&synqe->wr, (uintptr_t)wr);
@@ -1155,46 +1156,9 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
* If we replied during syncache_add (synqe->wr has been consumed),
* good. Otherwise, set it to 0 so that further syncache_respond
* attempts by the kernel will be ignored.
- *
- * The extra hold on the synqe makes sure that it is still around, even
- * if the listener has been dropped and the synqe was aborted and the
- * reply to the abort has removed and released the synqe from the synq
- * list.
*/
if (atomic_cmpset_ptr(&synqe->wr, (uintptr_t)wr, 0)) {
- INP_WLOCK(inp);
- if (__predict_false(inp->inp_flags & INP_DROPPED)) {
- /* listener closed. synqe must have been aborted. */
- KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
- ("%s: listener %p closed but synqe %p not aborted",
- __func__, inp, synqe));
-
- CTR5(KTR_CXGBE,
- "%s: stid %u, tid %u, lctx %p, synqe %p, ABORTED",
- __func__, stid, tid, lctx, synqe);
- INP_WUNLOCK(inp);
- free(wr, M_CXGBE);
- release_synqe(synqe); /* about to exit function */
- return (__LINE__);
- }
-
- /*
- * synqe aborted before TOM replied to PASS_ACCEPT_REQ. But
- * that can only happen if the listener was closed and we just
- * checked for that.
- */
- KASSERT(!(synqe->flags & TPF_ABORT_SHUTDOWN),
- ("%s: synqe %p aborted, but listener %p not dropped.",
- __func__, synqe, inp));
-
- /* Yank the synqe out of the lctx synq. */
- TAILQ_REMOVE(&lctx->synq, synqe, link);
- release_synqe(synqe); /* removed from synq list */
- inp = release_lctx(sc, lctx);
- if (inp)
- INP_WUNLOCK(inp);
-
/*
* syncache may or may not have a hold on the synqe, which may
* or may not be stashed in the original SYN mbuf passed to us.
@@ -1205,13 +1169,39 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
m->m_pkthdr.rcvif = ifp;
remove_tid(sc, synqe->tid);
- release_synqe(synqe); /* about to exit function */
free(wr, M_CXGBE);
+
+ /* Yank the synqe out of the lctx synq. */
+ INP_WLOCK(inp);
+ TAILQ_REMOVE(&lctx->synq, synqe, link);
+ release_synqe(synqe); /* removed from synq list */
+ inp = release_lctx(sc, lctx);
+ if (inp)
+ INP_WUNLOCK(inp);
+
REJECT_PASS_ACCEPT();
}
- release_synqe(synqe); /* about to exit function */
+
CTR5(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p, synqe %p, SYNACK",
__func__, stid, tid, lctx, synqe);
+
+ INP_WLOCK(inp);
+ synqe->flags |= TPF_SYNQE_HAS_L2TE;
+ if (__predict_false(inp->inp_flags & INP_DROPPED)) {
+ /*
+ * Listening socket closed but tod_listen_stop did not abort
+ * this tid because there was no L2T entry for the tid at that
+ * time. Abort it now. The reply to the abort will clean up.
+ */
+ CTR5(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p, synqe %p, ABORT",
+ __func__, stid, tid, lctx, synqe);
+ send_reset_synqe(tod, synqe);
+ INP_WUNLOCK(inp);
+
+ return (__LINE__);
+ }
+ INP_WUNLOCK(inp);
+
return (0);
reject:
CTR4(KTR_CXGBE, "%s: stid %u, tid %u, REJECT (%d)", __func__, stid, tid,
@@ -1293,15 +1283,12 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss,
__func__, stid, tid, synqe, synqe->flags, inp->inp_flags);
if (__predict_false(inp->inp_flags & INP_DROPPED)) {
- /*
- * The listening socket has closed. The TOM must have aborted
- * all the embryonic connections (including this one) that were
- * on the lctx's synq. do_abort_rpl for the tid is responsible
- * for cleaning up.
- */
- KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
- ("%s: listen socket dropped but tid %u not aborted.",
- __func__, tid));
+
+ if (synqe->flags & TPF_SYNQE_HAS_L2TE) {
+ KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
+ ("%s: listen socket closed but tid %u not aborted.",
+ __func__, tid));
+ }
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1321,7 +1308,12 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss,
toep = alloc_toepcb(pi, txqid, rxqid, M_NOWAIT);
if (toep == NULL) {
reset:
- /* The reply to this abort will perform final cleanup */
+ /*
+ * The reply to this abort will perform final cleanup. There is
+ * no need to check for HAS_L2TE here. We can be here only if
+ * we responded to the PASS_ACCEPT_REQ, and our response had the
+ * L2T idx.
+ */
send_reset_synqe(TOEDEV(ifp), synqe);
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
OpenPOWER on IntegriCloud