[PATCH] PCI: Disable async suspend/resume for Jmicron chip

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From 57edba9c677e47354846db951014dc4d5b13ce54 Mon Sep 17 00:00:00 2001
From: Zhang Rui <rui.zhang@xxxxxxxxx>
Date: Sun, 26 Jul 2015 14:15:36 +0800
Subject: [PATCH] PCI: Disable async suspend/resume for Jmicron chip

In https://bugzilla.kernel.org/show_bug.cgi?id=81551,
we found that Jmicron chip 361/363 is broken after resume if async noirq
(76569faa62 (PM / sleep: Asynchronous threads for resume_noirq)) is supported,
thus commit e6b7e41cdd (ata: Disabling the async PM for JMicron chip 363/361)
is introduced to fix this problem.
But then, we found that Jmicron chip 368 also has this problem, and it is decided
to disable the pm async feature for all the Jmicron chips.

But how to fix this was discussed in the mailing list for some time.
After some investigation, we believe that a proper fix is to disable
the async PM in PCI instead of ata driver, because, on this platform,
pci_resume_noirq() of IDE controller must happen after pci_resume_noirq()
of AHCI controller. But as .resume_noirq() of the pata_jmicron driver is
no-op, this suggests that it is the PCI common actions, aka,
pci_pm_default_resume_early(), have the dependency.
To fix this, using device_pm_wait_for_dev() in pata_jmicron driver can not
solve the dependency because pci_pm_default_resume_early() is invoked before
driver callback being invoked, plus, as it is the PCI common actions that
have the dependency, it is reasonable to fix it in PCI bus code,
rather than driver code.

This patch is made based on the patch from Liu Chuansheng at
https://lkml.org/lkml/2014/12/5/74
it reverts commit e6b7e41cdd ("ata: Disabling the async PM for JMicron
chip 363/361"), and introduces a PCI quirk to disable async PM for Jmicron
chips.

Reference: https://bugzilla.kernel.org/show_bug.cgi?id=81551
Tested-by: Jay <MyMailClone@xxxxxxxxxxx>
Tested-by: Barto <mister.freeman@xxxxxxxxxxx>
Signed-off-by: Zhang Rui <rui.zhang@xxxxxxxxx>
---
 drivers/ata/ahci.c         | 12 ------------
 drivers/ata/pata_jmicron.c | 12 ------------
 drivers/pci/quirks.c       | 15 +++++++++++++++
 3 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7e62751..26bb40d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1451,18 +1451,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	else if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
 		ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
 
-	/*
-	 * The JMicron chip 361/363 contains one SATA controller and one
-	 * PATA controller,for powering on these both controllers, we must
-	 * follow the sequence one by one, otherwise one of them can not be
-	 * powered on successfully, so here we disable the async suspend
-	 * method for these chips.
-	 */
-	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
-		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
-		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
-		device_disable_async_suspend(&pdev->dev);
-
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 47e418b..4d1a5d2 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -143,18 +143,6 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
-	/*
-	 * The JMicron chip 361/363 contains one SATA controller and one
-	 * PATA controller,for powering on these both controllers, we must
-	 * follow the sequence one by one, otherwise one of them can not be
-	 * powered on successfully, so here we disable the async suspend
-	 * method for these chips.
-	 */
-	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
-		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
-		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
-		device_disable_async_suspend(&pdev->dev);
-
 	return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
 }
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e9fd0e9..7a348de 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -29,6 +29,21 @@
 #include "pci.h"
 
 /*
+ * For JMicron chips, we need to disable the async_suspend method, otherwise
+ * they will hit the power-on issue when doing device resume, add one quick
+ * solution to disable the async_suspend method.
+ */
+static void pci_async_suspend_fixup(struct pci_dev *pdev)
+{
+	/*
+	 * disabling the async_suspend method for JMicron chips to
+	 * avoid device resuming issue.
+	 */
+	device_disable_async_suspend(&pdev->dev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, pci_async_suspend_fixup);
+
+/*
  * Decoding should be disabled for a PCI device during BAR sizing to avoid
  * conflict. But doing so may cause problems on host bridge and perhaps other
  * key system devices. For devices that need to have mmio decoding always-on,
-- 
1.9.1



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



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux