Kexec reboot does not reset PCI devices. If iwlwifi is left running, the next kernel can time out during probe, breaking networking after kexec: kernel: iwlwifi 0000:06:00.0: Host monitor block 0x22 vector 0x0 kernel: iwlwifi 0000:06:00.0: value [iter 0]: 0x00000000 kernel: iwlwifi 0000:06:00.0: probe with driver iwlwifi failed with error -110 Register a dedicated PCI shutdown callback: run the normal teardown path and then disable the PCI function and transition it to D3hot so the next kernel can re-initialize it reliably. Signed-off-by: Li Chen --- Changes in v2: - Don't reuse the ->remove callback for shutdown. - Disable the PCI function and set D3hot after teardown. drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index dc99e7ac4726..e950aab5a39d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1192,6 +1192,21 @@ static void iwl_pci_remove(struct pci_dev *pdev) iwl_pcie_gen1_2_remove(trans); } +static void iwl_pci_shutdown(struct pci_dev *pdev) +{ + struct iwl_trans *trans = pci_get_drvdata(pdev); + + if (trans) { + iwl_pcie_gen1_2_remove(trans); + pci_set_drvdata(pdev, NULL); + } + + pci_save_state(pdev); + pci_clear_master(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); +} + #ifdef CONFIG_PM_SLEEP static int iwl_pci_suspend(struct device *device) @@ -1325,6 +1340,7 @@ static struct pci_driver iwl_pci_driver = { .id_table = iwl_hw_card_ids, .probe = iwl_pci_probe, .remove = iwl_pci_remove, + .shutdown = iwl_pci_shutdown, .driver.pm = IWL_PM_OPS, .driver.coredump = iwl_pci_dump, }; -- 2.52.0