The resume code path of iwx(4) was improved during the k2k21 hackathon.
This patch merges the corresponding changes to iwm(4), such that iwm(4)
resumes directly in DVACT_WAKEUP instead of using the init task.

Tested by me on an 8265 device.

ok?

diff 02c3ac519701a4fe198f8ee3de592b34a39ee6f7 
d18bc0f805b2b0ec7e08f833f15080cb1614e08c
blob - 92f77754c4dd9d8a340a24bc2ce6f89ca77e0f84
blob + 2410b7d65756166edd8e68fed251c681eddb8851
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -550,7 +550,8 @@ void        iwm_attach_hook(struct device *);
 void   iwm_attach(struct device *, struct device *, void *);
 void   iwm_init_task(void *);
 int    iwm_activate(struct device *, int);
-int    iwm_resume(struct iwm_softc *);
+void   iwm_resume(struct iwm_softc *);
+int    iwm_wakeup(struct iwm_softc *);
 
 #if NBPFILTER > 0
 void   iwm_radiotap_attach(struct iwm_softc *);
@@ -1554,11 +1555,8 @@ int
 iwm_check_rfkill(struct iwm_softc *sc)
 {
        uint32_t v;
-       int s;
        int rv;
 
-       s = splnet();
-
        /*
         * "documentation" is not really helpful here:
         *  27: HW_RF_KILL_SW
@@ -1574,7 +1572,6 @@ iwm_check_rfkill(struct iwm_softc *sc)
                sc->sc_flags &= ~IWM_FLAG_RFKILL;
        }
 
-       splx(s);
        return rv;
 }
 
@@ -1622,8 +1619,6 @@ iwm_restore_interrupts(struct iwm_softc *sc)
 void
 iwm_disable_interrupts(struct iwm_softc *sc)
 {
-       int s = splnet();
-
        if (!sc->sc_msix) {
                IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
 
@@ -1636,8 +1631,6 @@ iwm_disable_interrupts(struct iwm_softc *sc)
                IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,
                    sc->sc_hw_init_mask);
        }
-
-       splx(s);
 }
 
 void
@@ -9679,18 +9672,8 @@ int
 iwm_init_hw(struct iwm_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       int err, i, ac, qid;
+       int err, i, ac, qid, s;
 
-       err = iwm_preinit(sc);
-       if (err)
-               return err;
-
-       err = iwm_start_hw(sc);
-       if (err) {
-               printf("%s: could not initialize hardware\n", DEVNAME(sc));
-               return err;
-       }
-
        err = iwm_run_init_mvm_ucode(sc, 0);
        if (err)
                return err;
@@ -9704,14 +9687,18 @@ iwm_init_hw(struct iwm_softc *sc)
        }
 
        /* Restart, this time with the regular firmware */
+       s = splnet();
        err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_REGULAR);
        if (err) {
                printf("%s: could not load firmware\n", DEVNAME(sc));
-               goto err;
+               splx(s);
+               return err;
        }
 
-       if (!iwm_nic_lock(sc))
+       if (!iwm_nic_lock(sc)) {
+               splx(s);
                return EBUSY;
+       }
 
        err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));
        if (err) {
@@ -9738,20 +9725,20 @@ iwm_init_hw(struct iwm_softc *sc)
        if (err) {
                printf("%s: could not init bt coex (error %d)\n",
                    DEVNAME(sc), err);
-               return err;
+               goto err;
        }
 
        if (isset(sc->sc_enabled_capa,
            IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {
                err = iwm_send_soc_conf(sc);
                if (err)
-                       return err;
+                       goto err;
        }
 
        if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
                err = iwm_send_dqa_cmd(sc);
                if (err)
-                       return err;
+                       goto err;
        }
 
        /* Add auxiliary station for scanning */
@@ -9859,6 +9846,7 @@ iwm_init_hw(struct iwm_softc *sc)
 
 err:
        iwm_nic_unlock(sc);
+       splx(s);
        return err;
 }
 
@@ -9902,6 +9890,16 @@ iwm_init(struct ifnet *ifp)
        KASSERT(sc->task_refs.refs == 0);
        refcnt_init(&sc->task_refs);
 
+       err = iwm_preinit(sc);
+       if (err)
+               return err;
+
+       err = iwm_start_hw(sc);
+       if (err) {
+               printf("%s: could not initialize hardware\n", DEVNAME(sc));
+               return err;
+       }
+
        err = iwm_init_hw(sc);
        if (err) {
                if (generation == sc->sc_generation)
@@ -11180,7 +11178,10 @@ iwm_attach(struct device *parent, struct device *self,
                return;
        }
 
-       /* Clear device-specific "PCI retry timeout" register (41h). */
+       /*
+        * We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
 
@@ -11576,12 +11577,15 @@ iwm_init_task(void *arg1)
        splx(s);
 }
 
-int
+void
 iwm_resume(struct iwm_softc *sc)
 {
        pcireg_t reg;
 
-       /* Clear device-specific "PCI retry timeout" register (41h). */
+       /*
+        * We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
 
@@ -11596,8 +11600,34 @@ iwm_resume(struct iwm_softc *sc)
        }
 
        iwm_disable_interrupts(sc);
+}
 
-       return iwm_start_hw(sc);
+int
+iwm_wakeup(struct iwm_softc *sc)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ifnet *ifp = &sc->sc_ic.ic_if;
+       int err;
+
+       refcnt_init(&sc->task_refs);
+
+       err = iwm_start_hw(sc);
+       if (err)
+               return err;
+
+       err = iwm_init_hw(sc);
+       if (err)
+               return err;
+
+       ifq_clr_oactive(&ifp->if_snd);
+       ifp->if_flags |= IFF_RUNNING;
+
+       if (ic->ic_opmode == IEEE80211_M_MONITOR)
+               ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+       else
+               ieee80211_begin_scan(ifp);
+
+       return 0;
 }
 
 int
@@ -11616,15 +11646,15 @@ iwm_activate(struct device *self, int act)
                }
                break;
        case DVACT_RESUME:
-               err = iwm_resume(sc);
-               if (err)
-                       printf("%s: could not initialize hardware\n",
-                           DEVNAME(sc));
+               iwm_resume(sc);
                break;
        case DVACT_WAKEUP:
-               /* Hardware should be up at this point. */
-               if (iwm_set_hw_ready(sc))
-                       task_add(systq, &sc->init_task);
+               if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) {
+                       err = iwm_wakeup(sc);
+                       if (err)
+                               printf("%s: could not initialize hardware\n",
+                                   DEVNAME(sc));
+               }
                break;
        }
 


Reply via email to