On Thu, 2025-03-27 at 05:35 +0200, Grumbach, Emmanuel wrote: > On Thu, 2025-03-27 at 00:35 +0000, Chris Bainbridge wrote: > > On Wed, Mar 26, 2025 at 04:36:12PM +0000, Grumbach, Emmanuel wrote: > > > We have all the fixes now in 6.13.7. > > > If you still have issues there, please report back and I'll try > > > to > > > find > > > some time to craft something. > > > > Yes, I still see this in 6.14.0 on every suspend/resume with laptop > > Lenovo Legion 7 16ACHg6. > > > > Can you give the attached patch a try? > Compile tested only. > > Thanks And here is a new version of the patch. Let me know how it goes. Thanks!
From 0d97696e947eeeecc4d0aff9afd3154e89c2ce0b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> Date: Thu, 27 Mar 2025 05:35:15 +0200 Subject: [PATCH] [BUGFIX] wifi: iwlwifi: don't warn if the NIC is gone in resume Some BIOSes decide to power gate the WLAN device during S3. Since iwlwifi doesn't expect this, it gets very noisy reporting that the device is no longer available. Wifi is still available because iwlwifi recovers, but it spews scary prints in the log. Fix that by failing gracefully. type=bugfix ticket=none fixes=I613d17c712de7a0d611cde4e14f37ebbe0c3c964 Fixes: e8bb19c1d590 ("wifi: iwlwifi: support fast resume") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219597 Change-Id: I569ca15eaaa774d633038a749cc6ec7448419714 Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 13 ++++++++++--- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 8 ++++---- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 11 ++++++++--- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index e8aa72da39d3..dae064246fd0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -595,7 +595,7 @@ IWL_EXPORT_SYMBOL(iwl_trans_read_config32); bool _iwl_trans_grab_nic_access(struct iwl_trans *trans) { - return iwl_trans_pcie_grab_nic_access(trans); + return iwl_trans_pcie_grab_nic_access(trans, false); } IWL_EXPORT_SYMBOL(_iwl_trans_grab_nic_access); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 0796a38b2d92..45dfd4e8f738 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1998,10 +1998,17 @@ static int _iwl_pci_resume(struct device *device, bool restore) * need to reset it completely. * Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan, * so assume that any bits there mean that the device is usable. + * For older devices, just try silently to grab the NIC. */ - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && - !iwl_read32(trans, CSR_FUNC_SCRATCH)) - device_was_powered_off = true; + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { + if (!iwl_read32(trans, CSR_FUNC_SCRATCH)) + device_was_powered_off = true; + } else { + if (!_iwl_trans_pcie_grab_nic_access(trans, true)) + device_was_powered_off = true; + else + iwl_trans_pcie_release_nic_access(trans); + } if (restore || device_was_powered_off) { trans->state = IWL_TRANS_NO_FW; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 809306e8c32f..46805a9e03c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -560,10 +560,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, struct device *dev); -bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); -#define _iwl_trans_pcie_grab_nic_access(trans) \ +bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent); +#define _iwl_trans_pcie_grab_nic_access(trans, silent) \ __cond_lock(nic_access_nobh, \ - likely(__iwl_trans_pcie_grab_nic_access(trans))) + likely(__iwl_trans_pcie_grab_nic_access(trans, silent))) void iwl_trans_pcie_check_product_reset_status(struct pci_dev *pdev); void iwl_trans_pcie_check_product_reset_mode(struct pci_dev *pdev); @@ -1130,7 +1130,7 @@ int iwl_trans_pci_request_firmware(struct iwl_trans *trans, void (*cont)(const struct firmware *fw, void *context)); #endif -bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); +bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent); void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans); /* transport gen 1 exported functions */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index a894b28d6f73..76655a2eff3d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2431,7 +2431,7 @@ EXPORT_SYMBOL(iwl_trans_pcie_reset); * This version doesn't disable BHs but rather assumes they're * already disabled. */ -bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) +bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) { int ret; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -2486,6 +2486,11 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) IWL_CFG_MAC_TYPE_MA) && trans->trans_cfg->integrated; + if (silent) { + spin_unlock(&trans_pcie->reg_lock); + return false; + } + WARN_ONCE(1, "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", cntrl); @@ -2515,12 +2520,12 @@ out: return true; } -bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) +bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) { bool ret; local_bh_disable(); - ret = __iwl_trans_pcie_grab_nic_access(trans); + ret = __iwl_trans_pcie_grab_nic_access(trans, silent); if (ret) { /* keep BHs disabled until iwl_trans_pcie_release_nic_access */ return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 5c1e63bf31d5..52da38ac653e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1023,7 +1023,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, * returned. This needs to be done only on NICs that have * apmg_wake_up_wa set (see above.) */ - if (!_iwl_trans_pcie_grab_nic_access(trans)) + if (!_iwl_trans_pcie_grab_nic_access(trans, false)) return -EIO; /* -- 2.49.0