aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNavdeep Parhar <np@FreeBSD.org>2024-07-25 01:43:54 +0000
committerNavdeep Parhar <np@FreeBSD.org>2024-08-05 12:56:22 +0000
commitfef0e39f64a1db796ded8777dbee71fc287f6107 (patch)
tree9d6c89b0707e49daa999ee08854a72fad9e252d6
parent6e744de1a3dc5dde8d2ee51e97a1224a01bdfb21 (diff)
downloadsrc-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.c14
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c3
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c58
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);
}