diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-10-12 10:45:22 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-10-12 10:45:22 +0000 |
commit | 849f9724d6a27cfc38e5c25037bb0d1eaaab36de (patch) | |
tree | e40f1810e2e9da9df71d3e53f9d0932dd7320729 /sys | |
parent | 5351a740c5303e6edb6c36a8b4805efb253ed343 (diff) |
Explicitly stop iwx(4) Rx block ack when roaming between access points.
This is similar to a recent fix committed to iwm(4).
Unlike iwm(4) we do not need to disable Tx aggregation queues in iwx(4).
Attempting to do so would cause fatal firmware errors.
Tested by jmc@ and myself.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_iwx.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 547f783e862..273ce81ca41 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwx.c,v 1.116 2021/10/12 10:44:33 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.117 2021/10/12 10:45:21 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -6950,17 +6950,32 @@ iwx_run_stop(struct iwx_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct iwx_node *in = (void *)ic->ic_bss; - int err; + struct ieee80211_node *ni = &in->in_ni; + int err, i; splassert(IPL_NET); - if (sc->sc_flags & IWX_FLAG_STA_ACTIVE) { - err = iwx_flush_sta(sc, in); - if (err) { - printf("%s: could not flush Tx path (error %d)\n", - DEVNAME(sc), err); - return err; - } + err = iwx_flush_sta(sc, in); + if (err) { + printf("%s: could not flush Tx path (error %d)\n", + DEVNAME(sc), err); + return err; + } + + /* + * Stop Rx BA sessions now. We cannot rely on the BA task + * for this when moving out of RUN state since it runs in a + * separate thread. + * Note that in->in_ni (struct ieee80211_node) already represents + * our new access point in case we are roaming between APs. + * This means we cannot rely on struct ieee802111_node to tell + * us which BA sessions exist. + */ + for (i = 0; i < nitems(sc->sc_rxba_data); i++) { + struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i]; + if (rxba->baid == IWX_RX_REORDER_DATA_INVALID_BAID) + continue; + iwx_sta_rx_agg(sc, ni, rxba->tid, 0, 0, 0, 0); } err = iwx_sf_config(sc, IWX_SF_INIT_OFF); @@ -7279,7 +7294,6 @@ iwx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { struct ifnet *ifp = IC2IFP(ic); struct iwx_softc *sc = ifp->if_softc; - int i; /* * Prevent attemps to transition towards the same state, unless @@ -7297,10 +7311,6 @@ iwx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) memset(sc->setkey_arg, 0, sizeof(sc->setkey_arg)); sc->setkey_cur = sc->setkey_tail = sc->setkey_nkeys = 0; iwx_del_task(sc, systq, &sc->mac_ctxt_task); - for (i = 0; i < nitems(sc->sc_rxba_data); i++) { - struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i]; - iwx_clear_reorder_buffer(sc, rxba); - } } sc->ns_nstate = nstate; |