Re: is L1 really disabled in iwlwifi

From: Bjorn Helgaas
Date: Fri May 10 2013 - 18:53:33 EST


[+cc Rafael, other pci_disable_link_state() users]

On Wed, May 01, 2013 at 11:13:15AM -0600, Bjorn Helgaas wrote:
> On Wed, May 1, 2013 at 2:31 AM, Emmanuel Grumbach <egrumbach@xxxxxxxxx> wrote:
> > [from Bjorn's mail]
> >> In Emmanuel's case, we don't get _OSC control, so
> >> pci_disable_link_state() does nothing.
> >
> > Right, but this is true with the specific log I sent to you. Is it
> > possible that another platform / BIOS, we *will* get _OSC control and
> > that pci_disable_link_state() will actually do something? In that case
> > I would prefer not to remove the call to pcie_disable_link_state().
>
> Yes, absolutely, on many platforms we will get _OSC control, and
> pci_disable_link_state() will work as expected. The problem is that
> the driver doesn't have a good way to know whether pci_disable_link()
> did anything or not.
>
> Today I think we have:
>
> 1) If the BIOS grants the OS permission to control PCIe services via
> _OSC, pci_disable_link_state() works and L1 will be disabled.
>
> 2) If the BIOS does not grant permission, pci_disable_link_state()
> does nothing and L1 may be enabled or not depending on what
> configuration the BIOS did.
>
> If the device really doesn't work reliably when L1 is enabled, we're
> currently at the mercy of the BIOS -- if the BIOS enables L1 but
> doesn't grant us permission via _OSC, L1 will remain enabled (as it is
> on your system).

I propose the following patch. Any comments?


commit cd11e3f87c4d2777cf8921c0454500c9baa54b46
Author: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Date: Fri May 10 15:54:35 2013 -0600

PCI/ASPM: Allow drivers to disable ASPM unconditionally

Some devices have hardware problems related to using ASPM. Drivers for
these devices use pci_disable_link_state() to prevent their device from
entering L0s or L1. But on platforms where the OS doesn't have permission
to manage ASPM, pci_disable_link_state() does nothing, and the driver has
no way to know this.

Therefore, if the BIOS enables ASPM but declines (either via the FADT
ACPI_FADT_NO_ASPM bit or the _OSC method) to allow the OS to manage it,
the device can still use ASPM and trip over the hardware issue.

This patch makes pci_disable_link_state() disable ASPM unconditionally,
regardless of whether the OS has permission to manage ASPM in general.

Reported-by: Emmanuel Grumbach <egrumbach@xxxxxxxxx>
Reference: https://lkml.kernel.org/r/CANUX_P3F5YhbZX3WGU-j1AGpbXb_T9Bis2ErhvKkFMtDvzatVQ@xxxxxxxxxxxxxx
Reference: https://bugzilla.kernel.org/show_bug.cgi?id=57331
Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index d320df6..9ef4ab8 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -718,15 +718,11 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
* pci_disable_link_state - disable pci device's link state, so the link will
* never enter specific states
*/
-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
- bool force)
+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;

- if (aspm_disabled && !force)
- return;
-
if (!pci_is_pcie(pdev))
return;

@@ -757,13 +753,13 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,

void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, false, false);
+ __pci_disable_link_state(pdev, state, false);
}
EXPORT_SYMBOL(pci_disable_link_state_locked);

void pci_disable_link_state(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, true, false);
+ __pci_disable_link_state(pdev, state, true);
}
EXPORT_SYMBOL(pci_disable_link_state);

@@ -781,7 +777,7 @@ void pcie_clear_aspm(struct pci_bus *bus)
__pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_CLKPM,
- false, true);
+ false);
}
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/