Let iwm(4) resume directly in DVACT_WAKEUP instead of running the init task.
authorstsp <stsp@openbsd.org>
Mon, 22 Nov 2021 10:23:42 +0000 (10:23 +0000)
committerstsp <stsp@openbsd.org>
Mon, 22 Nov 2021 10:23:42 +0000 (10:23 +0000)
Same change as made for iwx(4) some time ago.

tested by myself and bket@

sys/dev/pci/if_iwm.c

index 32d831f..7fd6b5c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwm.c,v 1.380 2021/11/19 13:05:19 stsp Exp $       */
+/*     $OpenBSD: if_iwm.c,v 1.381 2021/11/22 10:23:42 stsp Exp $       */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -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
@@ -9685,17 +9678,7 @@ int
 iwm_init_hw(struct iwm_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       int err, i, ac, qid;
-
-       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;
-       }
+       int err, i, ac, qid, s;
 
        err = iwm_run_init_mvm_ucode(sc, 0);
        if (err)
@@ -9710,14 +9693,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) {
@@ -9744,20 +9731,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 */
@@ -9865,6 +9852,7 @@ iwm_init_hw(struct iwm_softc *sc)
 
 err:
        iwm_nic_unlock(sc);
+       splx(s);
        return err;
 }
 
@@ -9908,6 +9896,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)
@@ -11187,7 +11185,10 @@ iwm_attach(struct device *parent, struct device *self, void *aux)
                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);
 
@@ -11583,12 +11584,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);
 
@@ -11603,8 +11607,34 @@ iwm_resume(struct iwm_softc *sc)
        }
 
        iwm_disable_interrupts(sc);
+}
+
+int
+iwm_wakeup(struct iwm_softc *sc)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ifnet *ifp = &sc->sc_ic.ic_if;
+       int err;
 
-       return iwm_start_hw(sc);
+       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
@@ -11623,15 +11653,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;
        }