public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Linux PCI <linux-pci@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Francois Romieu <romieu@fr.zoreil.com>,
	pm list <linux-pm@lists.linux-foundation.org>,
	Matthew Garrett <mjg@redhat.com>
Subject: [PATCH 4/12] PCI PM: Make it possible to force using INTx for PCIe PME signaling
Date: Sun, 27 Dec 2009 21:02:22 +0100	[thread overview]
Message-ID: <200912272102.22775.rjw@sisk.pl> (raw)
In-Reply-To: <200912272057.10443.rjw@sisk.pl>

From: Rafael J. Wysocki <rjw@sisk.pl>

Apparently, some machines may have problems with PCI run-time power
management if MSIs are used for the hative PCIe PME signaling.  In
particular, on the MSI Wind U-100 PCIe PME interrupts are not
generated by a PCIe root port after a resume from suspend to RAM, if
the system wake-up was triggered by a PME from the device attached to
this port.  [It doesn't help to free the interrupt on suspend and
request it back on resume, even if that is done along with disabling
the MSI and re-enabling it, respectively.]  However, if INTx
interrupts are used for this purpose on the same machine, everything
works just fine.

For this reason, add a kernel command line switch allowing one to
request that MSIs be not used for the native PCIe PME signaling,
introduce a DMI table allowing us to blacklist machines that need
this switch to be set by default and put the MSI Wind U-100 into this
table.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 Documentation/kernel-parameters.txt |    2 ++
 drivers/pci/pcie/pme/pcie_pme.c     |   14 +++++++++++++-
 drivers/pci/pcie/portdrv.h          |   17 +++++++++++++++++
 drivers/pci/pcie/portdrv_core.c     |   12 ++++++++++--
 drivers/pci/pcie/portdrv_pci.c      |   27 +++++++++++++++++++++++++++
 5 files changed, 69 insertions(+), 3 deletions(-)

Index: linux-2.6/drivers/pci/pcie/pme/pcie_pme.c
===================================================================
--- linux-2.6.orig/drivers/pci/pcie/pme/pcie_pme.c
+++ linux-2.6/drivers/pci/pcie/pme/pcie_pme.c
@@ -53,12 +53,22 @@ static bool pcie_pme_disabled;
  */
 static bool pcie_pme_force_enable;
 
+/*
+ * If this switch is set, MSI will not be used for PCIe PME signaling.  This
+ * causes the PCIe port driver to use INTx interrupts only, but it turns out
+ * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based
+ * wake-up from system sleep states.
+ */
+bool pcie_pme_msi_disabled;
+
 static int __init pcie_pme_setup(char *str)
 {
 	if (!strcmp(str, "off"))
 		pcie_pme_disabled = true;
 	else if (!strcmp(str, "force"))
 		pcie_pme_force_enable = true;
+	else if (!strcmp(str, "nomsi"))
+		pcie_pme_msi_disabled = true;
 	return 1;
 }
 __setup("pcie_pme=", pcie_pme_setup);
@@ -73,7 +83,9 @@ __setup("pcie_pme=", pcie_pme_setup);
  */
 static bool pcie_pme_platform_setup(struct pcie_device *srv)
 {
-	return !pcie_pme_platform_notify(srv) || pcie_pme_force_enable;
+	if (!pcie_pme_platform_notify(srv))
+		return true;
+	return pcie_pme_force_enable;
 }
 
 struct pcie_pme_service_data {
Index: linux-2.6/drivers/pci/pcie/portdrv_core.c
===================================================================
--- linux-2.6.orig/drivers/pci/pcie/portdrv_core.c
+++ linux-2.6/drivers/pci/pcie/portdrv_core.c
@@ -186,16 +186,24 @@ static int pcie_port_enable_msix(struct 
  */
 static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 {
-	int i, irq;
+	int i, irq = -1;
+
+	/* We have to use INTx if MSI cannot be used for PCIe PME. */
+	if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) {
+		if (dev->pin)
+			irq = dev->irq;
+		goto no_msi;
+	}
 
 	/* Try to use MSI-X if supported */
 	if (!pcie_port_enable_msix(dev, irqs, mask))
 		return 0;
+
 	/* We're not going to use MSI-X, so try MSI and fall back to INTx */
-	irq = -1;
 	if (!pci_enable_msi(dev) || dev->pin)
 		irq = dev->irq;
 
+ no_msi:
 	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
 		irqs[i] = irq;
 	irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
Index: linux-2.6/drivers/pci/pcie/portdrv_pci.c
===================================================================
--- linux-2.6.orig/drivers/pci/pcie/portdrv_pci.c
+++ linux-2.6/drivers/pci/pcie/portdrv_pci.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
+#include <linux/dmi.h>
 
 #include "portdrv.h"
 #include "aer/aerdrv.h"
@@ -274,10 +275,36 @@ static struct pci_driver pcie_portdriver
 	.driver.pm 	= PCIE_PORTDRV_PM_OPS,
 };
 
+static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d)
+{
+	pr_notice("%s detected: will not use MSI for PCIe PME signaling\n",
+			d->ident);
+	pcie_pme_disable_msi();
+	return 0;
+}
+
+static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = {
+	/*
+	 * Boxes that should not use MSI for PCIe PME signaling.
+	 */
+	{
+	 .callback = dmi_pcie_pme_disable_msi,
+	 .ident = "MSI Wind U-100",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR,
+		     		"MICRO-STAR INTERNATIONAL CO., LTD"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "U-100"),
+		     },
+	 },
+	 {}
+};
+
 static int __init pcie_portdrv_init(void)
 {
 	int retval;
 
+	dmi_check_system(pcie_portdrv_dmi_table);
+
 	retval = pcie_port_bus_register();
 	if (retval) {
 		printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
Index: linux-2.6/drivers/pci/pcie/portdrv.h
===================================================================
--- linux-2.6.orig/drivers/pci/pcie/portdrv.h
+++ linux-2.6/drivers/pci/pcie/portdrv.h
@@ -30,4 +30,21 @@ extern void pcie_port_device_remove(stru
 extern int __must_check pcie_port_bus_register(void);
 extern void pcie_port_bus_unregister(void);
 
+#ifdef CONFIG_PCIE_PME
+extern bool pcie_pme_msi_disabled;
+
+static inline void pcie_pme_disable_msi(void)
+{
+	pcie_pme_msi_disabled = true;
+}
+
+static inline bool pcie_pme_no_msi(void)
+{
+	return pcie_pme_msi_disabled;
+}
+#else /* !CONFIG_PCIE_PME */
+static inline void pcie_pme_disable_msi(void) {}
+static inline bool pcie_pme_no_msi(void) { return false; }
+#endif /* !CONFIG_PCIE_PME */
+
 #endif /* _PORTDRV_H_ */
Index: linux-2.6/Documentation/kernel-parameters.txt
===================================================================
--- linux-2.6.orig/Documentation/kernel-parameters.txt
+++ linux-2.6/Documentation/kernel-parameters.txt
@@ -1991,6 +1991,8 @@ and is between 256 and 4096 characters. 
 		force	Use native PCIe PME signaling even if the BIOS refuses
 			to allow the kernel to control the relevant PCIe config
 			registers.
+		nomsi	Do not use MSI for native PCIe PME signaling (this makes
+			all PCIe root ports use INTx for everything).
 
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 

  parent reply	other threads:[~2009-12-27 20:02 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <200912272057.10443.rjw@sisk.pl>
2009-12-27 19:59 ` [PATCH 1/12] PCI PM: Add function for checking PME status of devices Rafael J. Wysocki
2010-01-06 21:46   ` Jesse Barnes
2009-12-27 20:00 ` [PATCH 2/12] PCI / PM: Propagate wake-up enable for PCIe devices too Rafael J. Wysocki
2009-12-27 20:01 ` [PATCH 3/12] PCI PM: PCIe PME root port service driver (rev. 5) Rafael J. Wysocki
2009-12-27 20:02 ` Rafael J. Wysocki [this message]
2010-01-06 21:56   ` [PATCH 4/12] PCI PM: Make it possible to force using INTx for PCIe PME signaling Jesse Barnes
     [not found]   ` <20100106135625.14b37f10@jbarnes-piketon>
2010-01-06 22:02     ` Matthew Garrett
     [not found]     ` <20100106220214.GA25366@srcf.ucam.org>
2010-01-06 23:00       ` Rafael J. Wysocki
     [not found]       ` <201001070000.41807.rjw@sisk.pl>
2010-01-08 20:08         ` Len Brown
     [not found]         ` <alpine.LFD.2.00.1001081502010.4012@localhost.localdomain>
2010-01-08 20:25           ` Greg KH
2009-12-27 20:03 ` [PATCH 5/12] ACPI: Add infrastructure for refcounting GPE consumers Rafael J. Wysocki
2009-12-27 20:03 ` [PATCH 6/12] ACPI: Add support for new refcounted GPE API to drivers Rafael J. Wysocki
2009-12-27 20:04 ` [PATCH 7/12] ACPI: Remove old GPE API and transition code entirely to new one Rafael J. Wysocki
2009-12-27 20:05 ` [PATCH 8/12] ACPI / PM: Add more run-time wake-up fields Rafael J. Wysocki
2009-12-27 20:06 ` [PATCH 9/12] ACPI / PM: Introduce acpi_pm_wakeup_power() Rafael J. Wysocki
2009-12-27 20:07 ` [PATCH 10/12] PCI / ACPI / PM: Platform support for PCI PME wake-up (rev. 6) Rafael J. Wysocki
2009-12-27 20:08 ` [PATCH 11/12] PCI PM: Run-time callbacks for PCI bus type (rev. 2) Rafael J. Wysocki
2009-12-27 20:11 ` [PATCH 12/12] PM / r8169: Add simplified run-time PM support Rafael J. Wysocki
2010-01-01  1:29 ` [PATCH][RFC] e1000e: Add basic runtime PM support (was: [PATCH 0/12] PCI run-time PM support (rev. 2)) Rafael J. Wysocki
     [not found] ` <201001010229.24061.rjw@sisk.pl>
2010-01-01 19:03   ` [PATCH][RFC] e1000e: Add basic runtime PM support (rev. 2) " Rafael J. Wysocki
     [not found]   ` <201001012003.07722.rjw@sisk.pl>
2010-01-01 21:51     ` [PATCH][RFC] e1000e: Add basic runtime PM support (rev. 3) " Rafael J. Wysocki
     [not found] ` <200912272111.41728.rjw@sisk.pl>
2010-01-01 19:06   ` [PATCH 12/12] PM / r8169: Add simplified run-time PM support (rev. 2) Rafael J. Wysocki
     [not found] ` <200912272100.33117.rjw@sisk.pl>
2010-01-04 23:40   ` [PATCH 2/12] PCI / PM: Propagate wake-up enable for PCIe devices too Jesse Barnes
     [not found]   ` <20100104154038.76a9eedf@jbarnes-piketon>
2010-01-05 21:27     ` Rafael J. Wysocki
     [not found] ` <200912272101.25036.rjw@sisk.pl>
2010-01-06 21:53   ` [PATCH 3/12] PCI PM: PCIe PME root port service driver (rev. 5) Jesse Barnes
     [not found] ` <200912272106.26569.rjw@sisk.pl>
2010-01-06 22:00   ` [PATCH 9/12] ACPI / PM: Introduce acpi_pm_wakeup_power() Jesse Barnes
     [not found]   ` <20100106140035.6f622acf@jbarnes-piketon>
2010-01-06 23:11     ` Rafael J. Wysocki
     [not found]     ` <201001070011.49755.rjw@sisk.pl>
2010-01-07 21:11       ` Rafael J. Wysocki
     [not found] ` <200912272107.36486.rjw@sisk.pl>
2010-01-06 22:04   ` [PATCH 10/12] PCI / ACPI / PM: Platform support for PCI PME wake-up (rev. 6) Jesse Barnes
     [not found]   ` <20100106140414.6d03cef1@jbarnes-piketon>
2010-01-07 21:18     ` Rafael J. Wysocki
     [not found] ` <200912272108.25145.rjw@sisk.pl>
2010-01-06 22:06   ` [PATCH 11/12] PCI PM: Run-time callbacks for PCI bus type (rev. 2) Jesse Barnes
     [not found] ` <200912272105.30352.rjw@sisk.pl>
2010-01-08 20:39   ` [PATCH 8/12] ACPI / PM: Add more run-time wake-up fields Len Brown
     [not found]   ` <alpine.LFD.2.00.1001081536100.4012@localhost.localdomain>
2010-01-08 23:27     ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200912272102.22775.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=jbarnes@virtuousgeek.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=mjg@redhat.com \
    --cc=romieu@fr.zoreil.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox