Inlined patch does the following:

- removes functions in initialization per style(9) (splnet)
- removes double definition of IWX_NVM_GET_INFO
- removes unused 'ring' variable from iwx_sta_tx_agg_start
- removes unused 'iwx_tid_to_ac' array
- removes iwx_wait_tx_queues_empty function

Regarding the last thing - in our testing of a derivative product we've
found that sometimes the queue has some queued packets, the function has
to wait until all frames will be de-queued, but there are two problems:

1. There is no corresponding wakeup() for a ring, so this tsleep()
should always fail with EWOULDBLOCK, if we have queued frams. This leads
to the situation when needed softc flags aren't cleared, and on the next
join we get a panic with "MAC already added".

2. Linux driver does the flushes a slightly differently:

https://github.com/torvalds/linux/blob/master/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c#L5592

[...]
                if (drop) {
                        if (iwl_mvm_flush_sta(mvm, mvmsta, false))
                                IWL_ERR(mvm, "flush request fail\n");
                } else {
                        if (iwl_mvm_has_new_tx_api(mvm))
                                iwl_mvm_wait_sta_queues_empty(mvm, mvmsta);
                        else /* only used for !iwl_mvm_has_new_tx_api() below */
                                msk |= mvmsta->tfd_queue_msk;
                }
[...]

'drop' var is from Linux 80211 API - "If the parameter drop is set to
true, pending frames may be dropped." per
https://www.kernel.org/doc/html/v6.5/driver-api/80211/mac80211.html

As I can see OpenBSD driver tries to do both things, I propose to drop
this iwx_wait_tx_queues_empty function and follow 'drop = true' case
from the linux driver. Removal of this function has fixed panics for us.

Debugging and code have been sponsored by Serenity Cybersecurity, LLC.

diff /usr/src
commit - a8cd26ec98e16ab36053bf0a84ae2e4d88c286ea
path + /usr/src
blob - 612b68e3c6982a8ed4c0bcaca01d8c4e0a81d115
file + sys/dev/pci/if_iwx.c
--- sys/dev/pci/if_iwx.c
+++ sys/dev/pci/if_iwx.c
@@ -402,7 +402,6 @@ void        iwx_tx_update_byte_tbl(struct iwx_softc *, 
struct
            uint16_t, uint16_t);
 int    iwx_tx(struct iwx_softc *, struct mbuf *, struct ieee80211_node *);
 int    iwx_flush_sta_tids(struct iwx_softc *, int, uint16_t);
-int    iwx_wait_tx_queues_empty(struct iwx_softc *);
 int    iwx_drain_sta(struct iwx_softc *sc, struct iwx_node *, int);
 int    iwx_flush_sta(struct iwx_softc *, struct iwx_node *);
 int    iwx_beacon_filter_send_cmd(struct iwx_softc *,
@@ -2792,18 +2791,6 @@ iwx_nic_init(struct iwx_softc *sc)
        return 0;
 }
 
-/* Map a TID to an ieee80211_edca_ac category. */
-const uint8_t iwx_tid_to_ac[IWX_MAX_TID_COUNT] = {
-       EDCA_AC_BE,
-       EDCA_AC_BK,
-       EDCA_AC_BK,
-       EDCA_AC_BE,
-       EDCA_AC_VI,
-       EDCA_AC_VI,
-       EDCA_AC_VO,
-       EDCA_AC_VO,
-};
-
 /* Map ieee80211_edca_ac categories to firmware Tx FIFO. */
 const uint8_t iwx_ac_to_tx_fifo[] = {
        IWX_GEN2_EDCA_TX_FIFO_BE,
@@ -3548,8 +3535,10 @@ iwx_mac_ctxt_task(void *arg)
        struct iwx_softc *sc = arg;
        struct ieee80211com *ic = &sc->sc_ic;
        struct iwx_node *in = (void *)ic->ic_bss;
-       int err, s = splnet();
+       int err, s;
 
+       s = splnet();
+
        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) ||
            ic->ic_state != IEEE80211_S_RUN) {
                refcnt_rele_wake(&sc->task_refs);
@@ -3575,8 +3564,10 @@ iwx_phy_ctxt_task(void *arg)
        struct iwx_node *in = (void *)ic->ic_bss;
        struct ieee80211_node *ni = &in->in_ni;
        uint8_t chains, sco, vht_chan_width;
-       int err, s = splnet();
+       int err, s;
 
+       s = splnet();
+
        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) ||
            ic->ic_state != IEEE80211_S_RUN ||
            in->in_phyctxt == NULL) {
@@ -3668,7 +3659,6 @@ iwx_sta_tx_agg_start(struct iwx_softc *sc, struct ieee
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_tx_ba *ba;
        int err, qid;
-       struct iwx_tx_ring *ring;
 
        /* Ensure we can map this TID to an aggregation queue. */
        if (tid >= IWX_MAX_TID_COUNT)
@@ -3711,7 +3701,6 @@ iwx_sta_tx_agg_start(struct iwx_softc *sc, struct ieee
 
        ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
 
-       ring = &sc->txq[qid];
        ba->ba_timeout_val = 0;
        ieee80211_addba_resp_accept(ic, ni, tid);
        sc->aggqid[tid] = qid;
@@ -3723,9 +3712,11 @@ iwx_ba_task(void *arg)
        struct iwx_softc *sc = arg;
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_node *ni = ic->ic_bss;
-       int s = splnet();
+       int s;
        int tid;
 
+       s = splnet();
+
        for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
                if (sc->sc_flags & IWX_FLAG_SHUTDOWN)
                        break;
@@ -6429,31 +6420,7 @@ out:
        return err;
 }
 
-#define IWX_FLUSH_WAIT_MS      2000
-
 int
-iwx_wait_tx_queues_empty(struct iwx_softc *sc)
-{
-       int i, err;
-
-       for (i = 0; i < nitems(sc->txq); i++) {
-               struct iwx_tx_ring *ring = &sc->txq[i];
-
-               if (i == IWX_DQA_CMD_QUEUE)
-                       continue;
-
-               while (ring->queued > 0) {
-                       err = tsleep_nsec(ring, 0, "iwxflush",
-                           MSEC_TO_NSEC(IWX_FLUSH_WAIT_MS));
-                       if (err)
-                               return err;
-               }
-       }
-
-       return 0;
-}
-
-int
 iwx_drain_sta(struct iwx_softc *sc, struct iwx_node* in, int drain)
 {
        struct iwx_add_sta_cmd cmd;
@@ -6510,13 +6477,6 @@ iwx_flush_sta(struct iwx_softc *sc, struct iwx_node *i
                goto done;
        }
 
-       err = iwx_wait_tx_queues_empty(sc);
-       if (err) {
-               printf("%s: Could not empty Tx queues (error %d)\n",
-                   DEVNAME(sc), err);
-               goto done;
-       }
-
        err = iwx_drain_sta(sc, in, 0);
 done:
        sc->sc_flags &= ~IWX_FLAG_TXFLUSH;
@@ -7515,8 +7475,10 @@ iwx_clear_statistics(struct iwx_softc *sc)
 void
 iwx_add_task(struct iwx_softc *sc, struct taskq *taskq, struct task *task)
 {
-       int s = splnet();
+       int s;
 
+       s = splnet();
+
        if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {
                splx(s);
                return;
@@ -7617,8 +7579,10 @@ iwx_bgscan_done_task(void *arg)
        struct ieee80211com *ic = &sc->sc_ic;
        struct iwx_node *in = (void *)ic->ic_bss;
        struct ieee80211_node *ni = &in->in_ni;
-       int tid, err = 0, s = splnet();
+       int tid, err = 0, s;
 
+       s = splnet();
+
        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) ||
            (ic->ic_flags & IEEE80211_F_BGSCAN) == 0 ||
            ic->ic_state != IEEE80211_S_RUN) {
@@ -8540,8 +8504,10 @@ iwx_setkey_task(void *arg)
 {
        struct iwx_softc *sc = arg;
        struct iwx_setkey_task_arg *a;
-       int err = 0, s = splnet();
+       int err = 0, s;
 
+       s = splnet();
+
        while (sc->setkey_nkeys > 0) {
                if (err || (sc->sc_flags & IWX_FLAG_SHUTDOWN))
                        break;
@@ -8616,8 +8582,10 @@ iwx_newstate_task(void *psc)
        enum ieee80211_state nstate = sc->ns_nstate;
        enum ieee80211_state ostate = ic->ic_state;
        int arg = sc->ns_arg;
-       int err = 0, s = splnet();
+       int err = 0, s;
 
+       s = splnet();
+
        if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {
                /* iwx_stop() is waiting for us. */
                refcnt_rele_wake(&sc->task_refs);
@@ -9292,8 +9260,10 @@ iwx_stop(struct ifnet *ifp)
        struct iwx_softc *sc = ifp->if_softc;
        struct ieee80211com *ic = &sc->sc_ic;
        struct iwx_node *in = (void *)ic->ic_bss;
-       int i, s = splnet();
+       int i, s;
 
+       s = splnet();
+
        rw_assert_wrlock(&sc->ioctl_rwl);
 
        sc->sc_flags |= IWX_FLAG_SHUTDOWN; /* Disallow new tasks. */
@@ -11395,10 +11365,12 @@ iwx_init_task(void *arg1)
 {
        struct iwx_softc *sc = arg1;
        struct ifnet *ifp = &sc->sc_ic.ic_if;
-       int s = splnet();
+       int s;
        int generation = sc->sc_generation;
        int fatal = (sc->sc_flags & (IWX_FLAG_HW_ERR | IWX_FLAG_RFKILL));
 
+       s = splnet();
+
        rw_enter_write(&sc->ioctl_rwl);
        if (generation != sc->sc_generation) {
                rw_exit(&sc->ioctl_rwl);
blob - 8713b11a6ea8784f2d5fe115d1eea0e6aa691f0b
file + sys/dev/pci/if_iwxreg.h
--- sys/dev/pci/if_iwxreg.h
+++ sys/dev/pci/if_iwxreg.h
@@ -2016,7 +2016,6 @@ struct iwx_tx_queue_cfg_rsp {
 /* REGULATORY_AND_NVM group subcommand IDs */
 #define IWX_NVM_ACCESS_COMPLETE        0x00
 #define IWX_NVM_GET_INFO       0x02
-#define IWX_NVM_GET_INFO       0x02
 #define IWX_PNVM_INIT_COMPLETE 0xfe
 
 /*

Reply via email to