The branch main has been updated by np:

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

commit fef0e39f64a1db796ded8777dbee71fc287f6107
Author:     Navdeep Parhar <n...@freebsd.org>
AuthorDate: 2024-07-25 01:43:54 +0000
Commit:     Navdeep Parhar <n...@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);
 }
 

Reply via email to