igb: fix deadlock caused by taking RTNL in RPM resume path
Recent net core changes caused an issue with few Intel drivers (reportedly igb), where taking RTNL in RPM resume path results in a deadlock. See [0] for a bug report. I don't think the core changes are wrong, but taking RTNL in RPM resume path isn't needed. The Intel drivers are the only ones doing this. See [1] for a discussion on the issue. Following patch changes the RPM resume path to not take RTNL. [0] https://bugzilla.kernel.org/show_bug.cgi?id=215129 [1] https://lore.kernel.org/netdev/20211125074949.5f897431@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com/t/ Fixes:bd869245a3
("net: core: try to runtime-resume detached device in __dev_open") Fixes:f32a213765
("ethtool: runtime-resume netdev parent before ethtool ioctl ops") Tested-by: Martin Stolpe <martin.stolpe@gmail.com> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Link: https://lore.kernel.org/r/20211220201844.2714498-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
1f06f7d97f
Коммит
ac8c58f5b5
|
@ -9254,7 +9254,7 @@ static int __maybe_unused igb_suspend(struct device *dev)
|
|||
return __igb_shutdown(to_pci_dev(dev), NULL, 0);
|
||||
}
|
||||
|
||||
static int __maybe_unused igb_resume(struct device *dev)
|
||||
static int __maybe_unused __igb_resume(struct device *dev, bool rpm)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
|
@ -9297,17 +9297,24 @@ static int __maybe_unused igb_resume(struct device *dev)
|
|||
|
||||
wr32(E1000_WUS, ~0);
|
||||
|
||||
rtnl_lock();
|
||||
if (!rpm)
|
||||
rtnl_lock();
|
||||
if (!err && netif_running(netdev))
|
||||
err = __igb_open(netdev, true);
|
||||
|
||||
if (!err)
|
||||
netif_device_attach(netdev);
|
||||
rtnl_unlock();
|
||||
if (!rpm)
|
||||
rtnl_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __maybe_unused igb_resume(struct device *dev)
|
||||
{
|
||||
return __igb_resume(dev, false);
|
||||
}
|
||||
|
||||
static int __maybe_unused igb_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct net_device *netdev = dev_get_drvdata(dev);
|
||||
|
@ -9326,7 +9333,7 @@ static int __maybe_unused igb_runtime_suspend(struct device *dev)
|
|||
|
||||
static int __maybe_unused igb_runtime_resume(struct device *dev)
|
||||
{
|
||||
return igb_resume(dev);
|
||||
return __igb_resume(dev, true);
|
||||
}
|
||||
|
||||
static void igb_shutdown(struct pci_dev *pdev)
|
||||
|
@ -9442,7 +9449,7 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
|
|||
* @pdev: Pointer to PCI device
|
||||
*
|
||||
* Restart the card from scratch, as if from a cold-boot. Implementation
|
||||
* resembles the first-half of the igb_resume routine.
|
||||
* resembles the first-half of the __igb_resume routine.
|
||||
**/
|
||||
static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -9482,7 +9489,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
|
|||
*
|
||||
* This callback is called when the error recovery driver tells us that
|
||||
* its OK to resume normal operation. Implementation resembles the
|
||||
* second-half of the igb_resume routine.
|
||||
* second-half of the __igb_resume routine.
|
||||
*/
|
||||
static void igb_io_resume(struct pci_dev *pdev)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче