Patchwork PCI: Quirk for ASUS S3 issue

login
register
mail settings
Submitter AceLan Kao
Date July 4, 2012, 8:34 a.m.
Message ID <1341390851-22099-1-git-send-email-acelan.kao@canonical.com>
Download mbox | patch
Permalink /patch/168926/
State Not Applicable
Headers show

Comments

AceLan Kao - July 4, 2012, 8:34 a.m.
Attempt to suspend some ASUS systems causes hang. Power cycle required
to recover.
The root cause of this issue is result from the the BIOS will try to
disable USB which is already disabled by the driver.
BIOS will check the EHCI controller's PCI COMMAND register,
if it's not zero, then BIOS will think the USB is not disabled yet,
so it will try to disable USB again, and then hang in the BIOS code.
To resolve this, we should clear the EHCI controller's PCI COMMAND
register before entering S3. And this does no harm to the system,
since it'll switch off the power after enter S3, and the value in the
register will be reset by BIOS after wakeup.

Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=43064
BugLink: http://bugs.launchpad.net/bugs/951143

Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
---
 drivers/pci/quirks.c |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
AceLan Kao - July 4, 2012, 8:39 a.m.
Hi all,

I take the following weekday as personal leave days,
so I send out the patch earlier for discussion.
I'll read email next week.

Best regards,
AceLan Kao.

2012/7/4 AceLan Kao <acelan.kao@canonical.com>:
> Attempt to suspend some ASUS systems causes hang. Power cycle required
> to recover.
> The root cause of this issue is result from the the BIOS will try to
> disable USB which is already disabled by the driver.
> BIOS will check the EHCI controller's PCI COMMAND register,
> if it's not zero, then BIOS will think the USB is not disabled yet,
> so it will try to disable USB again, and then hang in the BIOS code.
> To resolve this, we should clear the EHCI controller's PCI COMMAND
> register before entering S3. And this does no harm to the system,
> since it'll switch off the power after enter S3, and the value in the
> register will be reset by BIOS after wakeup.
>
> Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=43064
> BugLink: http://bugs.launchpad.net/bugs/951143
>
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/pci/quirks.c |   19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 194b243a..d1bb4db 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -2955,6 +2955,25 @@ static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
>
> +/*
> + * ASUS BIOS will check the EHCI controller's PCI COMMAND register to see
> + * if the value is all zero. If not, BIOS will think the USB is not disabled
> + * and will try to disable USB. But, actually, USB is disabled by the driver
> + * while entering S3, so it'll hang in BIOS when it try to disable USB.
> + * Since it's going to enter S3, so it does no harm to clear the EHCI
> + * controller's PCI COMMAND register. And the value of the PCI COMMAND
> + * register value will be restored correctly after S3.
> + */
> +static void asus_clear_pci_command(struct pci_dev *dev)
> +{
> +       if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
> +               return;
> +
> +       pci_write_config_word(dev, PCI_COMMAND, 0);
> +}
> +DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x7808, asus_clear_memory_bit);
> +DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_ATI, 0x4396, asus_clear_memory_bit);
> +
>  static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
>                           struct pci_fixup *end)
>  {
> --
> 1.7.9.5
>

Patch

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 194b243a..d1bb4db 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2955,6 +2955,25 @@  static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
 
+/*
+ * ASUS BIOS will check the EHCI controller's PCI COMMAND register to see
+ * if the value is all zero. If not, BIOS will think the USB is not disabled
+ * and will try to disable USB. But, actually, USB is disabled by the driver
+ * while entering S3, so it'll hang in BIOS when it try to disable USB.
+ * Since it's going to enter S3, so it does no harm to clear the EHCI
+ * controller's PCI COMMAND register. And the value of the PCI COMMAND
+ * register value will be restored correctly after S3.
+ */
+static void asus_clear_pci_command(struct pci_dev *dev)
+{
+	if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
+		return;
+
+	pci_write_config_word(dev, PCI_COMMAND, 0);
+}
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x7808, asus_clear_memory_bit);
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_ATI, 0x4396, asus_clear_memory_bit);
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {