git: 7ce67909fa68 - main - iwm: clear persistence bit on 9000 series NICs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 12 Oct 2026 02:51:37 UTC
The branch main has been updated by adrian:
URL: https://cgit.FreeBSD.org/src/commit/?id=7ce67909fa683b22546b2ec8d635db1582b56bca
commit 7ce67909fa683b22546b2ec8d635db1582b56bca
Author: Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-10-12 02:50:50 +0000
Commit: Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-10-12 02:50:50 +0000
iwm: clear persistence bit on 9000 series NICs
From what I've gathered, this is to make sure that the firmware
clears state and is reloaded through hardware bring-up and
suspend/resume.
It may fix instability issues with the 9000 series NICs.
I'll need to test it out first.
Obtained from: OpenBSD a6e25c727a2214219715b51ba6af2221d7e0d674
Differential Revision: https://reviews.freebsd.org/D60078
---
sys/dev/iwm/if_iwm_pcie_trans.c | 25 +++++++++++++++++++++++++
sys/dev/iwm/if_iwm_pcie_trans.h | 1 +
2 files changed, 26 insertions(+)
diff --git a/sys/dev/iwm/if_iwm_pcie_trans.c b/sys/dev/iwm/if_iwm_pcie_trans.c
index 96134b4c9d81..ce7526b0377d 100644
--- a/sys/dev/iwm/if_iwm_pcie_trans.c
+++ b/sys/dev/iwm/if_iwm_pcie_trans.c
@@ -620,6 +620,26 @@ iwm_apm_stop(struct iwm_softc *sc)
IWM_DPRINTF(sc, IWM_DEBUG_TRANS, "%s: iwm apm stop\n", __func__);
}
+int
+iwm_clear_persistence_bit(struct iwm_softc *sc)
+{
+ uint32_t hpm, wprot;
+
+ hpm = iwm_read_prph(sc, IWM_HPM_DEBUG);
+ if (hpm != 0xa5a5a5a0 && (hpm & IWM_HPM_PERSISTENCE_BIT)) {
+ wprot = iwm_read_prph(sc, IWM_PREG_PRPH_WPROT_9000);
+ if (wprot & IWM_PREG_WFPM_ACCESS) {
+ device_printf(sc->sc_dev,
+ "cannot clear persistence bit\n");
+ return EPERM;
+ }
+ iwm_write_prph(sc, IWM_HPM_DEBUG,
+ hpm & ~IWM_HPM_PERSISTENCE_BIT);
+ }
+
+ return 0;
+}
+
/* iwlwifi pcie/trans.c */
int
iwm_start_hw(struct iwm_softc *sc)
@@ -629,6 +649,11 @@ iwm_start_hw(struct iwm_softc *sc)
if ((error = iwm_prepare_card_hw(sc)) != 0)
return error;
+ if (sc->cfg->device_family == IWM_DEVICE_FAMILY_9000) {
+ if ((error = iwm_clear_persistence_bit(sc)) != 0)
+ return error;
+ }
+
/* Reset the entire device */
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
DELAY(5000);
diff --git a/sys/dev/iwm/if_iwm_pcie_trans.h b/sys/dev/iwm/if_iwm_pcie_trans.h
index 8b00a3fd6a69..f55707e1c96f 100644
--- a/sys/dev/iwm/if_iwm_pcie_trans.h
+++ b/sys/dev/iwm/if_iwm_pcie_trans.h
@@ -128,6 +128,7 @@ extern int iwm_prepare_card_hw(struct iwm_softc *sc);
extern void iwm_apm_config(struct iwm_softc *sc);
extern int iwm_apm_init(struct iwm_softc *sc);
extern void iwm_apm_stop(struct iwm_softc *sc);
+extern int iwm_clear_persistence_bit(struct iwm_softc *sc);
extern int iwm_start_hw(struct iwm_softc *sc);
extern void iwm_set_pwr(struct iwm_softc *sc);
extern int iwm_pcie_rx_stop(struct iwm_softc *sc);