mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-02-24 01:29:59 +07:00
igc: fix page fault when thunderbolt is unplugged
[ Upstream commit 4b79959510e6612d80f8d86022e0cb44eee6f4a2 ] 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 [#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:13b5b7fd6a
("igc: Add support for Tx/Rx rings") Fixes:b03c49cde6
("igc: Save PTP time before a reset") Signed-off-by: Aaron Ma <aaron.ma@canonical.com> Tested-by: Dvora Fuxbrumer <dvorax.fuxbrumer@linux.intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
dfc7b6de8a
commit
6869a48a0a
@ -138,6 +138,9 @@ static void igc_release_hw_control(struct igc_adapter *adapter)
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 ctrl_ext;
|
||||
|
||||
if (!pci_device_is_present(adapter->pdev))
|
||||
return;
|
||||
|
||||
/* Let firmware take over control of h/w */
|
||||
ctrl_ext = rd32(IGC_CTRL_EXT);
|
||||
wr32(IGC_CTRL_EXT,
|
||||
@ -3782,26 +3785,29 @@ void igc_down(struct igc_adapter *adapter)
|
||||
|
||||
igc_ptp_suspend(adapter);
|
||||
|
||||
/* disable receives in the hardware */
|
||||
rctl = rd32(IGC_RCTL);
|
||||
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
if (pci_device_is_present(adapter->pdev)) {
|
||||
/* disable receives in the hardware */
|
||||
rctl = rd32(IGC_RCTL);
|
||||
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
}
|
||||
/* set trans_start so we don't get spurious watchdogs during reset */
|
||||
netif_trans_update(netdev);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
tctl = rd32(IGC_TCTL);
|
||||
tctl &= ~IGC_TCTL_EN;
|
||||
wr32(IGC_TCTL, tctl);
|
||||
/* flush both disables and wait for them to finish */
|
||||
wrfl();
|
||||
usleep_range(10000, 20000);
|
||||
if (pci_device_is_present(adapter->pdev)) {
|
||||
/* disable transmits in the hardware */
|
||||
tctl = rd32(IGC_TCTL);
|
||||
tctl &= ~IGC_TCTL_EN;
|
||||
wr32(IGC_TCTL, tctl);
|
||||
/* flush both disables and wait for them to finish */
|
||||
wrfl();
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
igc_irq_disable(adapter);
|
||||
igc_irq_disable(adapter);
|
||||
}
|
||||
|
||||
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
|
||||
|
||||
|
@ -557,7 +557,8 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
|
||||
|
||||
igc_ptp_time_save(adapter);
|
||||
if (pci_device_is_present(adapter->pdev))
|
||||
igc_ptp_time_save(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user