Skip to content

Commit 4b79959

Browse files
pyma1anguy11
authored andcommitted
igc: fix page fault when thunderbolt is unplugged
After unplug thunderbolt dock with i225, pciehp interrupt is triggered, remove call will read/write mmio address which is already disconnected, then cause page fault and make system hang. Check PCI state to remove device safely. Trace: BUG: unable to handle page fault for address: 000000000000b604 Oops: 0000 [kernel-patches#1] SMP NOPTI RIP: 0010:igc_rd32+0x1c/0x90 [igc] Call Trace: igc_ptp_suspend+0x6c/0xa0 [igc] igc_ptp_stop+0x12/0x50 [igc] igc_remove+0x7f/0x1c0 [igc] pci_device_remove+0x3e/0xb0 __device_release_driver+0x181/0x240 Fixes: 13b5b7f ("igc: Add support for Tx/Rx rings") Fixes: b03c49c ("igc: Save PTP time before a reset") Signed-off-by: Aaron Ma <[email protected]> Tested-by: Dvora Fuxbrumer <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent ffc9c3e commit 4b79959

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ static void igc_release_hw_control(struct igc_adapter *adapter)
149149
struct igc_hw *hw = &adapter->hw;
150150
u32 ctrl_ext;
151151

152+
if (!pci_device_is_present(adapter->pdev))
153+
return;
154+
152155
/* Let firmware take over control of h/w */
153156
ctrl_ext = rd32(IGC_CTRL_EXT);
154157
wr32(IGC_CTRL_EXT,
@@ -4449,26 +4452,29 @@ void igc_down(struct igc_adapter *adapter)
44494452

44504453
igc_ptp_suspend(adapter);
44514454

4452-
/* disable receives in the hardware */
4453-
rctl = rd32(IGC_RCTL);
4454-
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
4455-
/* flush and sleep below */
4456-
4455+
if (pci_device_is_present(adapter->pdev)) {
4456+
/* disable receives in the hardware */
4457+
rctl = rd32(IGC_RCTL);
4458+
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
4459+
/* flush and sleep below */
4460+
}
44574461
/* set trans_start so we don't get spurious watchdogs during reset */
44584462
netif_trans_update(netdev);
44594463

44604464
netif_carrier_off(netdev);
44614465
netif_tx_stop_all_queues(netdev);
44624466

4463-
/* disable transmits in the hardware */
4464-
tctl = rd32(IGC_TCTL);
4465-
tctl &= ~IGC_TCTL_EN;
4466-
wr32(IGC_TCTL, tctl);
4467-
/* flush both disables and wait for them to finish */
4468-
wrfl();
4469-
usleep_range(10000, 20000);
4467+
if (pci_device_is_present(adapter->pdev)) {
4468+
/* disable transmits in the hardware */
4469+
tctl = rd32(IGC_TCTL);
4470+
tctl &= ~IGC_TCTL_EN;
4471+
wr32(IGC_TCTL, tctl);
4472+
/* flush both disables and wait for them to finish */
4473+
wrfl();
4474+
usleep_range(10000, 20000);
44704475

4471-
igc_irq_disable(adapter);
4476+
igc_irq_disable(adapter);
4477+
}
44724478

44734479
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
44744480

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,8 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
849849
adapter->ptp_tx_skb = NULL;
850850
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
851851

852-
igc_ptp_time_save(adapter);
852+
if (pci_device_is_present(adapter->pdev))
853+
igc_ptp_time_save(adapter);
853854
}
854855

855856
/**

0 commit comments

Comments
 (0)