diff options
| author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2026-09-22 14:49:49 +0300 |
|---|---|---|
| committer | Miri Korenblit <miriam.rachel.korenblit@intel.com> | 2026-09-30 11:18:30 +0300 |
| commit | 0dabef3fff5f6d3cbe76c5582a4b74cb4aeb90bf (patch) | |
| tree | 7b05bec8376584cd4f1e900d4a80878f89916af5 /drivers/net/wireless | |
| parent | 41a0c1a0da925749f5db85e0baeb332d8e71c50e (diff) | |
| download | linux-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.c | 31 |
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)); |
