git: fef0e39f64a1 - main - cxgbe/t4_tom: bugfixes in stop/restart.

From: Navdeep Parhar <np_at_FreeBSD.org>
Date: Mon, 05 Aug 2024 13:01:30 UTC
The branch main has been updated by np:

URL: https://cgit.FreeBSD.org/src/commit/?id=fef0e39f64a1db796ded8777dbee71fc287f6107

commit fef0e39f64a1db796ded8777dbee71fc287f6107
Author:     Navdeep Parhar <np@FreeBSD.org>
AuthorDate: 2024-07-25 01:43:54 +0000
Commit:     Navdeep Parhar <np@FreeBSD.org>
CommitDate: 2024-08-05 12:56:22 +0000

    cxgbe/t4_tom: bugfixes in stop/restart.
    
    1. Remove toepcb from the toep_list on active open failure.
    2. Purge the wr_list for an L2T entry on an adpater stop.
    
    Fixes:  c1c524852f62 cxgbe/t4_tom: Implement uld_stop and uld_restart for ULD_TOM.
    MFC after:      2 weeks
    Sponsored by:   Chelsio Communications
---
 sys/dev/cxgbe/tom/t4_connect.c | 14 ++++++++++
 sys/dev/cxgbe/tom/t4_listen.c  |  3 +++
 sys/dev/cxgbe/tom/t4_tom.c     | 58 +++++++++++++++++++++++++-----------------
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index 1c98e70a4df5..99e4c222996d 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -115,10 +115,17 @@ act_open_failure_cleanup(struct adapter *sc, struct toepcb *toep, u_int status)
 	struct inpcb *inp = toep->inp;
 	struct toedev *tod = &toep->td->tod;
 	struct epoch_tracker et;
+	struct tom_data *td = sc->tom_softc;
 
 	if (toep->tid >= 0) {
 		free_atid(sc, toep->tid);
 		toep->tid = -1;
+		mtx_lock(&td->toep_list_lock);
+		if (toep->flags & TPF_IN_TOEP_LIST) {
+			toep->flags &= ~TPF_IN_TOEP_LIST;
+			TAILQ_REMOVE(&td->toep_list, toep, link);
+		}
+		mtx_unlock(&td->toep_list_lock);
 	}
 
 	CURVNET_SET(toep->vnet);
@@ -234,6 +241,7 @@ t4_connect(struct toedev *tod, struct socket *so, struct nhop_object *nh,
     struct sockaddr *nam)
 {
 	struct adapter *sc = tod->tod_softc;
+	struct tom_data *td;
 	struct toepcb *toep = NULL;
 	struct wrqe *wr = NULL;
 	if_t rt_ifp = nh->nh_ifp;
@@ -380,6 +388,12 @@ t4_connect(struct toedev *tod, struct socket *so, struct nhop_object *nh,
 	}
 
 	offload_socket(so, toep);
+	/* Add the TOE PCB to the active list */
+	td = toep->td;
+	mtx_lock(&td->toep_list_lock);
+	TAILQ_INSERT_TAIL(&td->toep_list, toep, link);
+	toep->flags |= TPF_IN_TOEP_LIST;
+	mtx_unlock(&td->toep_list_lock);
 	NET_EPOCH_ENTER(et);
 	rc = t4_l2t_send(sc, wr, toep->l2te);
 	NET_EPOCH_EXIT(et);
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index 897c5bcaab1e..f91d193c0fed 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -1090,7 +1090,10 @@ t4_offload_socket(struct toedev *tod, void *arg, struct socket *so)
 	update_tid(sc, synqe->tid, toep);
 	synqe->flags |= TPF_SYNQE_EXPANDED;
 	mtx_lock(&td->toep_list_lock);
+	/* Remove synqe from its list and add the TOE PCB to the active list. */
 	TAILQ_REMOVE(&td->synqe_list, synqe, link);
+	TAILQ_INSERT_TAIL(&td->toep_list, toep, link);
+	toep->flags |= TPF_IN_TOEP_LIST;
 	mtx_unlock(&td->toep_list_lock);
 	inp->inp_flowtype = (inp->inp_vflag & INP_IPV6) ?
 	    M_HASHTYPE_RSS_TCP_IPV6 : M_HASHTYPE_RSS_TCP_IPV4;
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 58a77ff93c86..9b1dcf304196 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -256,12 +256,6 @@ offload_socket(struct socket *so, struct toepcb *toep)
 	toep->inp = inp;
 	toep->flags |= TPF_ATTACHED;
 	in_pcbref(inp);
-
-	/* Add the TOE PCB to the active list */
-	mtx_lock(&td->toep_list_lock);
-	TAILQ_INSERT_HEAD(&td->toep_list, toep, link);
-	toep->flags |= TPF_IN_TOEP_LIST;
-	mtx_unlock(&td->toep_list_lock);
 }
 
 void
@@ -280,7 +274,6 @@ undo_offload_socket(struct socket *so)
 	struct inpcb *inp = sotoinpcb(so);
 	struct tcpcb *tp = intotcpcb(inp);
 	struct toepcb *toep = tp->t_toe;
-	struct tom_data *td = toep->td;
 	struct sockbuf *sb;
 
 	INP_WLOCK_ASSERT(inp);
@@ -303,11 +296,6 @@ undo_offload_socket(struct socket *so)
 	toep->flags &= ~TPF_ATTACHED;
 	if (in_pcbrele_wlocked(inp))
 		panic("%s: inp freed.", __func__);
-
-	mtx_lock(&td->toep_list_lock);
-	toep->flags &= ~TPF_IN_TOEP_LIST;
-	TAILQ_REMOVE(&td->toep_list, toep, link);
-	mtx_unlock(&td->toep_list_lock);
 }
 
 static void
@@ -331,6 +319,12 @@ release_offload_resources(struct toepcb *toep)
 		remove_tid(sc, tid, toep->ce ? 2 : 1);
 		release_tid(sc, tid, toep->ctrlq);
 		toep->tid = -1;
+		mtx_lock(&td->toep_list_lock);
+		if (toep->flags & TPF_IN_TOEP_LIST) {
+			toep->flags &= ~TPF_IN_TOEP_LIST;
+			TAILQ_REMOVE(&td->toep_list, toep, link);
+		}
+		mtx_unlock(&td->toep_list_lock);
 	}
 	if (toep->ce) {
 		t4_release_clip_entry(sc, toep->ce);
@@ -346,8 +340,6 @@ release_offload_resources(struct toepcb *toep)
 static void
 done_with_toepcb(struct toepcb *toep)
 {
-	struct tom_data *td = toep->td;
-
 	KASSERT(!(toep->flags & TPF_CPL_PENDING),
 	    ("%s: %p has CPL pending.", __func__, toep));
 	KASSERT(!(toep->flags & TPF_ATTACHED),
@@ -370,13 +362,7 @@ done_with_toepcb(struct toepcb *toep)
 	MPASS(toep->tid == -1);
 	MPASS(toep->l2te == NULL);
 	MPASS(toep->ce == NULL);
-
-	mtx_lock(&td->toep_list_lock);
-	if (toep->flags & TPF_IN_TOEP_LIST) {
-		toep->flags &= ~TPF_IN_TOEP_LIST;
-		TAILQ_REMOVE(&td->toep_list, toep, link);
-	}
-	mtx_unlock(&td->toep_list_lock);
+	MPASS((toep->flags & TPF_IN_TOEP_LIST) == 0);
 
 	free_toepcb(toep);
 }
@@ -2039,6 +2025,8 @@ stop_atids(struct adapter *sc)
 		if ((uintptr_t)toep >= (uintptr_t)&t->atid_tab[0] &&
 		    (uintptr_t)toep < (uintptr_t)&t->atid_tab[t->natids])
 			continue;
+		if (__predict_false(toep == NULL))
+			continue;
 		MPASS(toep->tid == atid);
 		MPASS(toep->incarnation == sc->incarnation);
 		/*
@@ -2052,6 +2040,8 @@ stop_atids(struct adapter *sc)
 		toep->tid = -1;
 #endif
 		mtx_lock(&td->toep_list_lock);
+		toep->flags &= ~TPF_IN_TOEP_LIST;
+		TAILQ_REMOVE(&td->toep_list, toep, link);
 		TAILQ_INSERT_TAIL(&td->stranded_atids, toep, link);
 		mtx_unlock(&td->toep_list_lock);
 	}
@@ -2109,16 +2099,32 @@ static void
 stop_tom_l2t(struct adapter *sc)
 {
 	struct l2t_data *d = sc->l2t;
+	struct tom_data *td = sc->tom_softc;
 	struct l2t_entry *e;
+	struct wrqe *wr;
 	int i;
 
+	/*
+	 * This task cannot be enqueued because L2 state changes are not being
+	 * processed.  But if it's already scheduled or running then we need to
+	 * wait for it to cleanup the atids in the unsent_wr_list.
+	 */
+	taskqueue_drain(taskqueue_thread, &td->reclaim_wr_resources);
+	MPASS(STAILQ_EMPTY(&td->unsent_wr_list));
+
 	for (i = 0; i < d->l2t_size; i++) {
 		e = &d->l2tab[i];
 		mtx_lock(&e->lock);
 		if (e->state == L2T_STATE_VALID)
 			e->state = L2T_STATE_RESOLVING;
-		if (!STAILQ_EMPTY(&e->wr_list))
-			CXGBE_UNIMPLEMENTED("l2t e->wr_list");
+		/*
+		 * stop_atids is going to clean up _all_ atids in use, including
+		 * these that were pending L2 resolution.  Just discard the WRs.
+		 */
+		while ((wr = STAILQ_FIRST(&e->wr_list)) != NULL) {
+			STAILQ_REMOVE_HEAD(&e->wr_list, link);
+			free(wr, M_CXGBE);
+		}
 		mtx_unlock(&e->lock);
 	}
 }
@@ -2140,6 +2146,12 @@ t4_tom_stop(struct adapter *sc)
 		stop_tids(sc);
 	taskqueue_enqueue(taskqueue_thread, &td->cleanup_stranded_tids);
 
+	/*
+	 * L2T and atid_tab are restarted before t4_tom_restart so this assert
+	 * is not valid in t4_tom_restart.  This is the next best place for it.
+	 */
+	MPASS(STAILQ_EMPTY(&td->unsent_wr_list));
+
 	return (0);
 }