summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2026-09-22 14:49:49 +0300
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>2026-09-30 11:18:30 +0300
commit0dabef3fff5f6d3cbe76c5582a4b74cb4aeb90bf (patch)
tree7b05bec8376584cd4f1e900d4a80878f89916af5 /drivers/net/wireless
parent41a0c1a0da925749f5db85e0baeb332d8e71c50e (diff)
downloadlinux-next-0dabef3fff5f6d3cbe76c5582a4b74cb4aeb90bf.tar.gz
linux-next-0dabef3fff5f6d3cbe76c5582a4b74cb4aeb90bf.zip
wifi: iwlwifi: poke the config space in case of command timeout
There is a race between the PCI link power save flow and the notification flow from the firmware. The firmware prepares the notification in DRAM and then sends an MSI-X message to interrupt the CPU and let it know it can handle the notification. In case the PCI link goes L1.2 between the access to the DRAM to copy the notification and the MSI-X interrupt, the host won't be interrupted. Add a work-around to cope with this situation. If the command response was not received after 200ms, read the config space of the device just to wake up the link. This will allow the MSI-X interrupt to go through and the CPU will get the interrupt. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221501 Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Link: https://patch.msgid.link/20260922144819.ef433f3da32b.I017c1c7a1dd3ac6f111d4640966968b82f37e291@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
index 060074c2871b..fae5beed2ecb 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
@@ -2560,6 +2560,7 @@ next_queue:
}
}
+#define HOST_COMPLETE_QUICK_TIMEOUT msecs_to_jiffies(200)
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
@@ -2593,10 +2594,32 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
return ret;
}
- ret = wait_event_timeout(trans_pcie->wait_command_queue,
- !test_bit(STATUS_SYNC_HCMD_ACTIVE,
- &trans->status),
- HOST_COMPLETE_TIMEOUT);
+ /*
+ * There is a race between the PCI link power save flows and the
+ * notification / MSI-X interrupt in the firmware.
+ * If we didn't get a response after 200ms, poke the config space
+ * to force a wake-up of the PCI link.
+ */
+ for (int i = 0; i < 2; i++) {
+ ret = wait_event_timeout(trans_pcie->wait_command_queue,
+ !test_bit(STATUS_SYNC_HCMD_ACTIVE,
+ &trans->status),
+ i == 0 ? HOST_COMPLETE_QUICK_TIMEOUT :
+ HOST_COMPLETE_TIMEOUT);
+ if (ret)
+ break;
+
+ if (i == 0) {
+ u32 val;
+
+ pci_read_config_dword(trans_pcie->pci_dev,
+ PCI_VENDOR_ID, &val);
+ IWL_DEBUG_HC(trans,
+ "write_ptr: %d: no response after %ums poking config space\n",
+ txq->write_ptr,
+ jiffies_to_msecs(HOST_COMPLETE_QUICK_TIMEOUT));
+ }
+ }
if (!ret) {
IWL_ERR(trans, "Error sending %s: time out after %dms.\n",
cmd_str, jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));