Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 231074
b: refs/heads/master
c: fe31e69
h: refs/heads/master
v: v3
  • Loading branch information
Rafael J. Wysocki authored and Jesse Barnes committed Dec 23, 2010
1 parent 6894592 commit 0c724d3
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 99a0fadf561e1f553c08f0a29f8b2578f55dd5f0
refs/heads/master: fe31e69740eddc7316071ed5165fed6703c8cd12
27 changes: 4 additions & 23 deletions trunk/drivers/pci/pcie/pme.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
#include "../pci.h"
#include "portdrv.h"

#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */

/*
* 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
Expand Down Expand Up @@ -73,22 +70,6 @@ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
pci_write_config_word(dev, rtctl_pos, rtctl);
}

/**
* pcie_pme_clear_status - Clear root port PME interrupt status.
* @dev: PCIe root port or event collector.
*/
static void pcie_pme_clear_status(struct pci_dev *dev)
{
int rtsta_pos;
u32 rtsta;

rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;

pci_read_config_dword(dev, rtsta_pos, &rtsta);
rtsta |= PCI_EXP_RTSTA_PME;
pci_write_config_dword(dev, rtsta_pos, rtsta);
}

/**
* pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#.
* @bus: PCI bus to scan.
Expand Down Expand Up @@ -253,7 +234,7 @@ static void pcie_pme_work_fn(struct work_struct *work)
* Clear PME status of the port. If there are other
* pending PMEs, the status will be set again.
*/
pcie_pme_clear_status(port);
pcie_clear_root_pme_status(port);

spin_unlock_irq(&data->lock);
pcie_pme_handle_request(port, rtsta & 0xffff);
Expand Down Expand Up @@ -378,7 +359,7 @@ static int pcie_pme_probe(struct pcie_device *srv)

port = srv->port;
pcie_pme_interrupt_enable(port, false);
pcie_pme_clear_status(port);
pcie_clear_root_pme_status(port);

ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv);
if (ret) {
Expand All @@ -402,7 +383,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)

spin_lock_irq(&data->lock);
pcie_pme_interrupt_enable(port, false);
pcie_pme_clear_status(port);
pcie_clear_root_pme_status(port);
data->noirq = true;
spin_unlock_irq(&data->lock);

Expand All @@ -422,7 +403,7 @@ static int pcie_pme_resume(struct pcie_device *srv)

spin_lock_irq(&data->lock);
data->noirq = false;
pcie_pme_clear_status(port);
pcie_clear_root_pme_status(port);
pcie_pme_interrupt_enable(port, true);
spin_unlock_irq(&data->lock);

Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/pci/pcie/portdrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ extern void pcie_port_bus_unregister(void);

struct pci_dev;

extern void pcie_clear_root_pme_status(struct pci_dev *dev);

#ifdef CONFIG_PCIE_PME
extern bool pcie_pme_msi_disabled;

Expand Down
25 changes: 14 additions & 11 deletions trunk/drivers/pci/pcie/portdrv_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,17 +241,17 @@ static int get_port_device_capability(struct pci_dev *dev)
int cap_mask;
int err;

if (pcie_ports_disabled)
return 0;

err = pcie_port_platform_notify(dev, &cap_mask);
if (pcie_ports_auto) {
if (err) {
pcie_no_aspm();
return 0;
}
} else {
if (!pcie_ports_auto) {
cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
| PCIE_PORT_SERVICE_VC;
if (pci_aer_available())
cap_mask |= PCIE_PORT_SERVICE_AER;
} else if (err) {
return 0;
}

pos = pci_pcie_cap(dev);
Expand Down Expand Up @@ -349,15 +349,18 @@ int pcie_port_device_register(struct pci_dev *dev)
int status, capabilities, i, nr_service;
int irqs[PCIE_PORT_DEVICE_MAXSERVICES];

/* Get and check PCI Express port services */
capabilities = get_port_device_capability(dev);
if (!capabilities)
return -ENODEV;

/* Enable PCI Express port device */
status = pci_enable_device(dev);
if (status)
return status;

/* Get and check PCI Express port services */
capabilities = get_port_device_capability(dev);
if (!capabilities) {
pcie_no_aspm();
return 0;
}

pci_set_master(dev);
/*
* Initialize service irqs. Don't use service devices that
Expand Down
37 changes: 33 additions & 4 deletions trunk/drivers/pci/pcie/portdrv_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ __setup("pcie_ports=", pcie_port_setup);

/* global data */

/**
* pcie_clear_root_pme_status - Clear root port PME interrupt status.
* @dev: PCIe root port or event collector.
*/
void pcie_clear_root_pme_status(struct pci_dev *dev)
{
int rtsta_pos;
u32 rtsta;

rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;

pci_read_config_dword(dev, rtsta_pos, &rtsta);
rtsta |= PCI_EXP_RTSTA_PME;
pci_write_config_dword(dev, rtsta_pos, rtsta);
}

static int pcie_portdrv_restore_config(struct pci_dev *dev)
{
int retval;
Expand All @@ -69,13 +85,28 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
}

#ifdef CONFIG_PM
static int pcie_port_resume_noirq(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);

/*
* Some BIOSes forget to clear Root PME Status bits after system wakeup
* which breaks ACPI-based runtime wakeup on PCI Express, so clear those
* bits now just in case (shouldn't hurt).
*/
if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
pcie_clear_root_pme_status(pdev);
return 0;
}

static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.suspend = pcie_port_device_suspend,
.resume = pcie_port_device_resume,
.freeze = pcie_port_device_suspend,
.thaw = pcie_port_device_resume,
.poweroff = pcie_port_device_suspend,
.restore = pcie_port_device_resume,
.resume_noirq = pcie_port_resume_noirq,
};

#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
Expand Down Expand Up @@ -327,10 +358,8 @@ static int __init pcie_portdrv_init(void)
{
int retval;

if (pcie_ports_disabled) {
pcie_no_aspm();
return -EACCES;
}
if (pcie_ports_disabled)
return pci_register_driver(&pcie_portdriver);

dmi_check_system(pcie_portdrv_dmi_table);

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/pci_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,8 @@
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTSTA 32 /* Root Status */
#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
Expand Down

0 comments on commit 0c724d3

Please sign in to comment.