diff options
author | Navdeep Parhar <np@FreeBSD.org> | 2024-07-25 01:43:54 +0000 |
---|---|---|
committer | Navdeep Parhar <np@FreeBSD.org> | 2024-08-05 12:56:22 +0000 |
commit | fef0e39f64a1db796ded8777dbee71fc287f6107 (patch) | |
tree | 9d6c89b0707e49daa999ee08854a72fad9e252d6 | |
parent | 6e744de1a3dc5dde8d2ee51e97a1224a01bdfb21 (diff) | |
download | src-fef0e39f64a1db796ded8777dbee71fc287f6107.tar.gz src-fef0e39f64a1db796ded8777dbee71fc287f6107.zip |
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
-rw-r--r-- | sys/dev/cxgbe/tom/t4_connect.c | 14 | ||||
-rw-r--r-- | sys/dev/cxgbe/tom/t4_listen.c | 3 | ||||
-rw-r--r-- | 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); } |