mirror of https://gitee.com/openkylin/linux.git
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
|
* @pdev: pointer to PCI device struct
|
||||||
* @state: bit-mask of ASPM states to disable
|
* @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.
|
* 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;
|
struct pci_dev *parent = pdev->bus->self;
|
||||||
u16 aspm_dis_mask = 0;
|
u16 aspm_dis_mask = 0;
|
||||||
|
@ -6399,7 +6400,10 @@ static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
||||||
"L1" : "");
|
"L1" : "");
|
||||||
|
|
||||||
#ifdef CONFIG_PCIEASPM
|
#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
|
/* Double-check ASPM control. If not disabled by the above, the
|
||||||
* BIOS is preventing that from happening (or CONFIG_PCIEASPM is
|
* 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);
|
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
|
#ifdef CONFIG_PM
|
||||||
static int __e1000_resume(struct pci_dev *pdev)
|
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)
|
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
|
||||||
aspm_disable_flag |= PCIE_LINK_STATE_L1;
|
aspm_disable_flag |= PCIE_LINK_STATE_L1;
|
||||||
if (aspm_disable_flag)
|
if (aspm_disable_flag)
|
||||||
e1000e_disable_aspm(pdev, aspm_disable_flag);
|
e1000e_disable_aspm_locked(pdev, aspm_disable_flag);
|
||||||
|
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue