aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-12-19 09:57:16 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-12-23 15:54:03 -0500
commitfe31e69740eddc7316071ed5165fed6703c8cd12 (patch)
treeb58f193d7176bfe19ae975fec7ff42d7e242e359 /drivers
parent99a0fadf561e1f553c08f0a29f8b2578f55dd5f0 (diff)
PCI/PCIe: Clear Root PME Status bits early during system resume
I noticed that PCI Express PMEs don't work on my Toshiba Portege R500 after the system has been woken up from a sleep state by a PME (through Wake-on-LAN). After some investigation it turned out that the BIOS didn't clear the Root PME Status bit in the root port that received the wakeup PME and since the Requester ID was also set in the port's Root Status register, any subsequent PMEs didn't trigger interrupts. This problem can be avoided by clearing the Root PME Status bits in all PCI Express root ports during early resume. For this purpose, add an early resume routine to the PCIe port driver and make this driver be always registered, even if pci_ports_disable is set (in which case the driver's only function is to provide the early resume callback). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/pcie/pme.c27
-rw-r--r--drivers/pci/pcie/portdrv.h2
-rw-r--r--drivers/pci/pcie/portdrv_core.c25
-rw-r--r--drivers/pci/pcie/portdrv_pci.c37
4 files changed, 53 insertions, 38 deletions
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 2f3c90407227..073f0308c6b2 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -26,9 +26,6 @@
26#include "../pci.h" 26#include "../pci.h"
27#include "portdrv.h" 27#include "portdrv.h"
28 28
29#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
30#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
31
32/* 29/*
33 * If this switch is set, MSI will not be used for PCIe PME signaling. This 30 * If this switch is set, MSI will not be used for PCIe PME signaling. This
34 * causes the PCIe port driver to use INTx interrupts only, but it turns out 31 * causes the PCIe port driver to use INTx interrupts only, but it turns out
@@ -74,22 +71,6 @@ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
74} 71}
75 72
76/** 73/**
77 * pcie_pme_clear_status - Clear root port PME interrupt status.
78 * @dev: PCIe root port or event collector.
79 */
80static void pcie_pme_clear_status(struct pci_dev *dev)
81{
82 int rtsta_pos;
83 u32 rtsta;
84
85 rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;
86
87 pci_read_config_dword(dev, rtsta_pos, &rtsta);
88 rtsta |= PCI_EXP_RTSTA_PME;
89 pci_write_config_dword(dev, rtsta_pos, rtsta);
90}
91
92/**
93 * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#. 74 * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#.
94 * @bus: PCI bus to scan. 75 * @bus: PCI bus to scan.
95 * 76 *
@@ -253,7 +234,7 @@ static void pcie_pme_work_fn(struct work_struct *work)
253 * Clear PME status of the port. If there are other 234 * Clear PME status of the port. If there are other
254 * pending PMEs, the status will be set again. 235 * pending PMEs, the status will be set again.
255 */ 236 */
256 pcie_pme_clear_status(port); 237 pcie_clear_root_pme_status(port);
257 238
258 spin_unlock_irq(&data->lock); 239 spin_unlock_irq(&data->lock);
259 pcie_pme_handle_request(port, rtsta & 0xffff); 240 pcie_pme_handle_request(port, rtsta & 0xffff);
@@ -378,7 +359,7 @@ static int pcie_pme_probe(struct pcie_device *srv)
378 359
379 port = srv->port; 360 port = srv->port;
380 pcie_pme_interrupt_enable(port, false); 361 pcie_pme_interrupt_enable(port, false);
381 pcie_pme_clear_status(port); 362 pcie_clear_root_pme_status(port);
382 363
383 ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); 364 ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv);
384 if (ret) { 365 if (ret) {
@@ -402,7 +383,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)
402 383
403 spin_lock_irq(&data->lock); 384 spin_lock_irq(&data->lock);
404 pcie_pme_interrupt_enable(port, false); 385 pcie_pme_interrupt_enable(port, false);
405 pcie_pme_clear_status(port); 386 pcie_clear_root_pme_status(port);
406 data->noirq = true; 387 data->noirq = true;
407 spin_unlock_irq(&data->lock); 388 spin_unlock_irq(&data->lock);
408 389
@@ -422,7 +403,7 @@ static int pcie_pme_resume(struct pcie_device *srv)
422 403
423 spin_lock_irq(&data->lock); 404 spin_lock_irq(&data->lock);
424 data->noirq = false; 405 data->noirq = false;
425 pcie_pme_clear_status(port); 406 pcie_clear_root_pme_status(port);
426 pcie_pme_interrupt_enable(port, true); 407 pcie_pme_interrupt_enable(port, true);
427 spin_unlock_irq(&data->lock); 408 spin_unlock_irq(&data->lock);
428 409
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 7b5aba0a3291..8fcc03598b29 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -35,6 +35,8 @@ extern void pcie_port_bus_unregister(void);
35 35
36struct pci_dev; 36struct pci_dev;
37 37
38extern void pcie_clear_root_pme_status(struct pci_dev *dev);
39
38#ifdef CONFIG_PCIE_PME 40#ifdef CONFIG_PCIE_PME
39extern bool pcie_pme_msi_disabled; 41extern bool pcie_pme_msi_disabled;
40 42
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index a9c222d79ebc..5130d0d22390 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -241,17 +241,17 @@ static int get_port_device_capability(struct pci_dev *dev)
241 int cap_mask; 241 int cap_mask;
242 int err; 242 int err;
243 243
244 if (pcie_ports_disabled)
245 return 0;
246
244 err = pcie_port_platform_notify(dev, &cap_mask); 247 err = pcie_port_platform_notify(dev, &cap_mask);
245 if (pcie_ports_auto) { 248 if (!pcie_ports_auto) {
246 if (err) {
247 pcie_no_aspm();
248 return 0;
249 }
250 } else {
251 cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP 249 cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
252 | PCIE_PORT_SERVICE_VC; 250 | PCIE_PORT_SERVICE_VC;
253 if (pci_aer_available()) 251 if (pci_aer_available())
254 cap_mask |= PCIE_PORT_SERVICE_AER; 252 cap_mask |= PCIE_PORT_SERVICE_AER;
253 } else if (err) {
254 return 0;
255 } 255 }
256 256
257 pos = pci_pcie_cap(dev); 257 pos = pci_pcie_cap(dev);
@@ -349,15 +349,18 @@ int pcie_port_device_register(struct pci_dev *dev)
349 int status, capabilities, i, nr_service; 349 int status, capabilities, i, nr_service;
350 int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; 350 int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
351 351
352 /* Get and check PCI Express port services */
353 capabilities = get_port_device_capability(dev);
354 if (!capabilities)
355 return -ENODEV;
356
357 /* Enable PCI Express port device */ 352 /* Enable PCI Express port device */
358 status = pci_enable_device(dev); 353 status = pci_enable_device(dev);
359 if (status) 354 if (status)
360 return status; 355 return status;
356
357 /* Get and check PCI Express port services */
358 capabilities = get_port_device_capability(dev);
359 if (!capabilities) {
360 pcie_no_aspm();
361 return 0;
362 }
363
361 pci_set_master(dev); 364 pci_set_master(dev);
362 /* 365 /*
363 * Initialize service irqs. Don't use service devices that 366 * Initialize service irqs. Don't use service devices that
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index f9033e190fb6..e0610bda1dea 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -57,6 +57,22 @@ __setup("pcie_ports=", pcie_port_setup);
57 57
58/* global data */ 58/* global data */
59 59
60/**
61 * pcie_clear_root_pme_status - Clear root port PME interrupt status.
62 * @dev: PCIe root port or event collector.
63 */
64void pcie_clear_root_pme_status(struct pci_dev *dev)
65{
66 int rtsta_pos;
67 u32 rtsta;
68
69 rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;
70
71 pci_read_config_dword(dev, rtsta_pos, &rtsta);
72 rtsta |= PCI_EXP_RTSTA_PME;
73 pci_write_config_dword(dev, rtsta_pos, rtsta);
74}
75
60static int pcie_portdrv_restore_config(struct pci_dev *dev) 76static int pcie_portdrv_restore_config(struct pci_dev *dev)
61{ 77{
62 int retval; 78 int retval;
@@ -69,6 +85,20 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
69} 85}
70 86
71#ifdef CONFIG_PM 87#ifdef CONFIG_PM
88static int pcie_port_resume_noirq(struct device *dev)
89{
90 struct pci_dev *pdev = to_pci_dev(dev);
91
92 /*
93 * Some BIOSes forget to clear Root PME Status bits after system wakeup
94 * which breaks ACPI-based runtime wakeup on PCI Express, so clear those
95 * bits now just in case (shouldn't hurt).
96 */
97 if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
98 pcie_clear_root_pme_status(pdev);
99 return 0;
100}
101
72static const struct dev_pm_ops pcie_portdrv_pm_ops = { 102static const struct dev_pm_ops pcie_portdrv_pm_ops = {
73 .suspend = pcie_port_device_suspend, 103 .suspend = pcie_port_device_suspend,
74 .resume = pcie_port_device_resume, 104 .resume = pcie_port_device_resume,
@@ -76,6 +106,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
76 .thaw = pcie_port_device_resume, 106 .thaw = pcie_port_device_resume,
77 .poweroff = pcie_port_device_suspend, 107 .poweroff = pcie_port_device_suspend,
78 .restore = pcie_port_device_resume, 108 .restore = pcie_port_device_resume,
109 .resume_noirq = pcie_port_resume_noirq,
79}; 110};
80 111
81#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) 112#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
@@ -327,10 +358,8 @@ static int __init pcie_portdrv_init(void)
327{ 358{
328 int retval; 359 int retval;
329 360
330 if (pcie_ports_disabled) { 361 if (pcie_ports_disabled)
331 pcie_no_aspm(); 362 return pci_register_driver(&pcie_portdriver);
332 return -EACCES;
333 }
334 363
335 dmi_check_system(pcie_portdrv_dmi_table); 364 dmi_check_system(pcie_portdrv_dmi_table);
336 365