aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-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