git: b4c35d4622d5 - main - iwx: fix and clean up suspend/resume path

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Fri, 14 Nov 2025 02:37:35 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=b4c35d4622d522c92bb080ee51e4a351e9d71897

commit b4c35d4622d522c92bb080ee51e4a351e9d71897
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-11-12 21:01:40 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-11-14 02:36:25 +0000

    iwx: fix and clean up suspend/resume path
    
    I noticed a couple of things were happening:
    
    * during suspend, I'd get a timeout in the NIC lock path (which
      sets a bit on the NIC to say that the host wants to talk to it);
    * resume wouldn't come back - scan commands would fail, and you'd have
      to reinit the NIC again for it to work.
    
    The thing is:
    
    * the suspend path should already shut down the NIC by shutting down all
      the VAPs (and the last VAP should call ic_parent to bring it down), and
    * the resume path should already bring up the NIC by bringing up each VAP,
      and the first VAP to be brought up calls ic_parent to bring it up.
    
    So instead, I've shuffled around the code to just double check the
    hardware state is consistent /before/ ieee80211_suspend_all() and
    ieee80211_resume_all() is called.
    
    This both fixes the errant hardware timeout during suspend, and it
    fixes resume to work.
    
    Locally tested:
    
    * AX210, STA mode, both hardware ACPI suspend/resume and devctl suspend
      and devctl resume
    
    Differential Revision:  https://reviews.freebsd.org/D53721
    Reviewed by:    thj
---
 sys/dev/iwx/if_iwx.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
index 91f5baee9680..dac1c563c593 100644
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -10711,9 +10711,13 @@ iwx_suspend(device_t dev)
 	struct iwx_softc *sc = device_get_softc(dev);
 	struct ieee80211com *ic = &sc->sc_ic;
 
-	if (sc->sc_flags & IWX_FLAG_HW_INITED) {
-		ieee80211_suspend_all(ic);
+	/*
+	 * Suspend everything first, then shutdown hardware if it's
+	 * still up.
+	 */
+	ieee80211_suspend_all(ic);
 
+	if (sc->sc_flags & IWX_FLAG_HW_INITED) {
 		iwx_stop(sc);
 		sc->sc_flags &= ~IWX_FLAG_HW_INITED;
 	}
@@ -10725,7 +10729,6 @@ iwx_resume(device_t dev)
 {
 	struct iwx_softc *sc = device_get_softc(dev);
 	struct ieee80211com *ic = &sc->sc_ic;
-	int err;
 
 	/*
 	 * We disable the RETRY_TIMEOUT register (0x41) to keep
@@ -10735,15 +10738,15 @@ iwx_resume(device_t dev)
 
 	IWX_LOCK(sc);
 
-	err = iwx_init(sc);
-	if (err) {
-		iwx_stop_device(sc);
-		IWX_UNLOCK(sc);
-		return err;
+	/* Stop the hardware here if it's still thought of as "up" */
+	if (sc->sc_flags & IWX_FLAG_HW_INITED) {
+		iwx_stop(sc);
+		sc->sc_flags &= ~IWX_FLAG_HW_INITED;
 	}
 
 	IWX_UNLOCK(sc);
 
+	/* Start the VAPs, which will bring the hardware back up again */
 	ieee80211_resume_all(ic);
 	return (0);
 }