Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Nov 2012 21:05:51 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r243682 - user/np/stable_9_toe/sys/dev/cxgbe/tom
Message-ID:  <201211292105.qATL5pp6055467@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Thu Nov 29 21:05:50 2012
New Revision: 243682
URL: http://svnweb.freebsd.org/changeset/base/243682

Log:
  Pull in r243680 and  r243681 from head.

Modified:
  user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_cpl_io.c
  user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_ddp.c
  user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_listen.c
  user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_tom.h
Directory Properties:
  user/np/stable_9_toe/sys/   (props changed)
  user/np/stable_9_toe/sys/dev/   (props changed)

Modified: user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_cpl_io.c
==============================================================================
--- user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_cpl_io.c	Thu Nov 29 19:39:27 2012	(r243681)
+++ user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_cpl_io.c	Thu Nov 29 21:05:50 2012	(r243682)
@@ -786,6 +786,29 @@ do_peer_close(struct sge_iq *iq, const s
 	KASSERT(opcode == CPL_PEER_CLOSE,
 	    ("%s: unexpected opcode 0x%x", __func__, opcode));
 	KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
+
+	if (__predict_false(toep->flags & TPF_SYNQE)) {
+#ifdef INVARIANTS
+		struct synq_entry *synqe = (void *)toep;
+
+		INP_WLOCK(synqe->lctx->inp);
+		if (synqe->flags & TPF_SYNQE_HAS_L2TE) {
+			KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
+			    ("%s: listen socket closed but tid %u not aborted.",
+			    __func__, tid));
+		} else {
+			/*
+			 * do_pass_accept_req is still running and will
+			 * eventually take care of this tid.
+			 */
+		}
+		INP_WUNLOCK(synqe->lctx->inp);
+#endif
+		CTR4(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x)", __func__, tid,
+		    toep, toep->flags);
+		return (0);
+	}
+
 	KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
 
 	INP_INFO_WLOCK(&V_tcbinfo);
@@ -1090,15 +1113,27 @@ do_rx_data(struct sge_iq *iq, const stru
 	struct socket *so;
 	struct sockbuf *sb;
 	int len;
+	uint32_t ddp_placed = 0;
 
 	if (__predict_false(toep->flags & TPF_SYNQE)) {
-		/*
-		 * do_pass_establish failed and must be attempting to abort the
-		 * synqe's tid.  Meanwhile, the T4 has sent us data for such a
-		 * connection.
-		 */
-		KASSERT(toep->flags & TPF_ABORT_SHUTDOWN,
-		    ("%s: synqe and tid isn't being aborted.", __func__));
+#ifdef INVARIANTS
+		struct synq_entry *synqe = (void *)toep;
+
+		INP_WLOCK(synqe->lctx->inp);
+		if (synqe->flags & TPF_SYNQE_HAS_L2TE) {
+			KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
+			    ("%s: listen socket closed but tid %u not aborted.",
+			    __func__, tid));
+		} else {
+			/*
+			 * do_pass_accept_req is still running and will
+			 * eventually take care of this tid.
+			 */
+		}
+		INP_WUNLOCK(synqe->lctx->inp);
+#endif
+		CTR4(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x)", __func__, tid,
+		    toep, toep->flags);
 		m_freem(m);
 		return (0);
 	}
@@ -1120,13 +1155,8 @@ do_rx_data(struct sge_iq *iq, const stru
 
 	tp = intotcpcb(inp);
 
-#ifdef INVARIANTS
-	if (__predict_false(tp->rcv_nxt != be32toh(cpl->seq))) {
-		log(LOG_ERR,
-		    "%s: unexpected seq# %x for TID %u, rcv_nxt %x\n",
-		    __func__, be32toh(cpl->seq), toep->tid, tp->rcv_nxt);
-	}
-#endif
+	if (__predict_false(tp->rcv_nxt != be32toh(cpl->seq)))
+		ddp_placed = be32toh(cpl->seq) - tp->rcv_nxt;
 
 	tp->rcv_nxt += len;
 	KASSERT(tp->rcv_wnd >= len, ("%s: negative window size", __func__));
@@ -1173,12 +1203,20 @@ do_rx_data(struct sge_iq *iq, const stru
 		int changed = !(toep->ddp_flags & DDP_ON) ^ cpl->ddp_off;
 
 		if (changed) {
-			if (__predict_false(!(toep->ddp_flags & DDP_SC_REQ))) {
-				/* XXX: handle this if legitimate */
-				panic("%s: unexpected DDP state change %d",
-				    __func__, cpl->ddp_off);
+			if (toep->ddp_flags & DDP_SC_REQ)
+				toep->ddp_flags ^= DDP_ON | DDP_SC_REQ;
+			else {
+				KASSERT(cpl->ddp_off == 1,
+				    ("%s: DDP switched on by itself.",
+				    __func__));
+
+				/* Fell out of DDP mode */
+				toep->ddp_flags &= ~(DDP_ON | DDP_BUF0_ACTIVE |
+				    DDP_BUF1_ACTIVE);
+
+				if (ddp_placed)
+					insert_ddp_data(toep, ddp_placed);
 			}
-			toep->ddp_flags ^= DDP_ON | DDP_SC_REQ;
 		}
 
 		if ((toep->ddp_flags & DDP_OK) == 0 &&

Modified: user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_ddp.c
==============================================================================
--- user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_ddp.c	Thu Nov 29 19:39:27 2012	(r243681)
+++ user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_ddp.c	Thu Nov 29 21:05:50 2012	(r243682)
@@ -205,6 +205,42 @@ release_ddp_resources(struct toepcb *toe
 	}
 }
 
+/* XXX: handle_ddp_data code duplication */
+void
+insert_ddp_data(struct toepcb *toep, uint32_t n)
+{
+	struct inpcb *inp = toep->inp;
+	struct tcpcb *tp = intotcpcb(inp);
+	struct sockbuf *sb = &inp->inp_socket->so_rcv;
+	struct mbuf *m;
+
+	INP_WLOCK_ASSERT(inp);
+	SOCKBUF_LOCK_ASSERT(sb);
+
+	m = m_get(M_NOWAIT, MT_DATA);
+	if (m == NULL)
+		CXGBE_UNIMPLEMENTED("mbuf alloc failure");
+	m->m_len = n;
+	m->m_flags |= M_DDP;	/* Data is already where it should be */
+	m->m_data = "nothing to see here";
+
+	tp->rcv_nxt += n;
+#ifndef USE_DDP_RX_FLOW_CONTROL
+	KASSERT(tp->rcv_wnd >= n, ("%s: negative window size", __func__));
+	tp->rcv_wnd -= n;
+#endif
+
+	KASSERT(toep->sb_cc >= sb->sb_cc,
+	    ("%s: sb %p has more data (%d) than last time (%d).",
+	    __func__, sb, sb->sb_cc, toep->sb_cc));
+	toep->rx_credits += toep->sb_cc - sb->sb_cc;
+#ifdef USE_DDP_RX_FLOW_CONTROL
+	toep->rx_credits -= n;	/* adjust for F_RX_FC_DDP */
+#endif
+	sbappendstream_locked(sb, m);
+	toep->sb_cc = sb->sb_cc;
+}
+
 /* SET_TCB_FIELD sent as a ULP command looks like this */
 #define LEN__SET_TCB_FIELD_ULP (sizeof(struct ulp_txpkt) + \
     sizeof(struct ulptx_idata) + sizeof(struct cpl_set_tcb_field_core))

Modified: user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_listen.c
==============================================================================
--- user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_listen.c	Thu Nov 29 19:39:27 2012	(r243681)
+++ user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_listen.c	Thu Nov 29 21:05:50 2012	(r243682)
@@ -282,8 +282,8 @@ send_reset_synqe(struct toedev *tod, str
 
 	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, struc
 	 * 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, co
 	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, co
 	 * 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, co
 			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, con
 	    __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, con
 	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);

Modified: user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_tom.h
==============================================================================
--- user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_tom.h	Thu Nov 29 19:39:27 2012	(r243681)
+++ user/np/stable_9_toe/sys/dev/cxgbe/tom/t4_tom.h	Thu Nov 29 21:05:50 2012	(r243682)
@@ -67,6 +67,7 @@ enum {
 	TPF_SYNQE_NEEDFREE = (1 << 9),	/* synq_entry was malloc'd separately */
 	TPF_SYNQE_TCPDDP   = (1 << 10),	/* ulp_mode TCPDDP in toepcb */
 	TPF_SYNQE_EXPANDED = (1 << 11),	/* toepcb ready, tid context updated */
+	TPF_SYNQE_HAS_L2TE = (1 << 12),	/* we've replied to PASS_ACCEPT_REQ */
 };
 
 enum {
@@ -272,4 +273,5 @@ int t4_soreceive_ddp(struct socket *, st
     struct mbuf **, struct mbuf **, int *);
 void enable_ddp(struct adapter *, struct toepcb *toep);
 void release_ddp_resources(struct toepcb *toep);
+void insert_ddp_data(struct toepcb *, uint32_t);
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211292105.qATL5pp6055467>