e1000e: fix locking issue with e1000e_disable_aspm
e1000e_disable_aspm called pci_disable_link_state_locked which requires pci_bus_sem to be held, but is also called from places where this semaphore was not previously acquired. This patch implements two flavors of disable_aspm, one that acquires the lock, and the other (_locked) which should be called when the semaphore is already acquired. Signed-off-by: Yanir Lubetkin <yanirx.lubetkin@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
73cd63598d
commit
beb0a1520b
|
@ -6354,13 +6354,14 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
|
|||
}
|
||||
|
||||
/**
|
||||
* e1000e_disable_aspm - Disable ASPM states
|
||||
* __e1000e_disable_aspm - Disable ASPM states
|
||||
* @pdev: pointer to PCI device struct
|
||||
* @state: bit-mask of ASPM states to disable
|
||||
* @locked: indication if this context holds pci_bus_sem locked.
|
||||
*
|
||||
* Some devices *must* have certain ASPM states disabled per hardware errata.
|
||||
**/
|
||||
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
||||
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state, int locked)
|
||||
{
|
||||
struct pci_dev *parent = pdev->bus->self;
|
||||
u16 aspm_dis_mask = 0;
|
||||
|
@ -6399,7 +6400,10 @@ static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
|||
"L1" : "");
|
||||
|
||||
#ifdef CONFIG_PCIEASPM
|
||||
pci_disable_link_state_locked(pdev, state);
|
||||
if (locked)
|
||||
pci_disable_link_state_locked(pdev, state);
|
||||
else
|
||||
pci_disable_link_state(pdev, state);
|
||||
|
||||
/* Double-check ASPM control. If not disabled by the above, the
|
||||
* BIOS is preventing that from happening (or CONFIG_PCIEASPM is
|
||||
|
@ -6422,6 +6426,32 @@ static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
|||
aspm_dis_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_disable_aspm - Disable ASPM states.
|
||||
* @pdev: pointer to PCI device struct
|
||||
* @state: bit-mask of ASPM states to disable
|
||||
*
|
||||
* This function acquires the pci_bus_sem!
|
||||
* Some devices *must* have certain ASPM states disabled per hardware errata.
|
||||
**/
|
||||
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
||||
{
|
||||
__e1000e_disable_aspm(pdev, state, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_disable_aspm_locked Disable ASPM states.
|
||||
* @pdev: pointer to PCI device struct
|
||||
* @state: bit-mask of ASPM states to disable
|
||||
*
|
||||
* This function must be called with pci_bus_sem acquired!
|
||||
* Some devices *must* have certain ASPM states disabled per hardware errata.
|
||||
**/
|
||||
static void e1000e_disable_aspm_locked(struct pci_dev *pdev, u16 state)
|
||||
{
|
||||
__e1000e_disable_aspm(pdev, state, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int __e1000_resume(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -6435,7 +6465,7 @@ static int __e1000_resume(struct pci_dev *pdev)
|
|||
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
|
||||
aspm_disable_flag |= PCIE_LINK_STATE_L1;
|
||||
if (aspm_disable_flag)
|
||||
e1000e_disable_aspm(pdev, aspm_disable_flag);
|
||||
e1000e_disable_aspm_locked(pdev, aspm_disable_flag);
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
|
|
Loading…
Reference in New Issue