Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit beb0a152 authored by Yanir Lubetkin's avatar Yanir Lubetkin Committed by Jeff Kirsher
Browse files

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: default avatarYanir Lubetkin <yanirx.lubetkin@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 73cd6359
Loading
Loading
Loading
Loading
+34 −4
Original line number Diff line number Diff line
@@ -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
	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);