Commit c7f48656 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Jesse Barnes

PCI PM: PCIe PME root port service driver

PCIe native PME detection mechanism is based on interrupts generated
by root ports or event collectors every time a PCIe device sends a
PME message upstream.

Once a PME message has been sent by an endpoint device and received
by its root port (or event collector in the case of root complex
integrated endpoints), the Requester ID from the message header is
registered in the root port's Root Status register.  At the same
time, the PME Status bit of the Root Status register is set to
indicate that there's a PME to handle.  If PCIe PME interrupt is
enabled for the root port, it generates an interrupt once the PME
Status has been set.  After receiving the interrupt, the kernel can
identify the PCIe device that generated the PME using the Requester
ID from the root port's Root Status register. [For details, see PCI
Express Base Specification, Rev. 2.0.]

Implement a driver for the PCIe PME root port service working in
accordance with the above description.

Based on a patch from Shaohua Li <shaohua.li@intel.com>.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 58ff4633
......@@ -1998,6 +1998,12 @@ and is between 256 and 4096 characters. It is defined in the file
force Enable ASPM even on devices that claim not to support it.
WARNING: Forcing ASPM on may cause system lockups.
pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
off Do not use native PCIe PME signaling.
force Use native PCIe PME signaling even if the BIOS refuses
to allow the kernel to control the relevant PCIe config
registers.
pcmv= [HW,PCMCIA] BadgePAD 4
pd. [PARIDE]
......
......@@ -46,3 +46,7 @@ config PCIEASPM_DEBUG
help
This enables PCI Express ASPM debug support. It will add per-device
interface to control ASPM.
config PCIE_PME
def_bool y
depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI
......@@ -11,3 +11,5 @@ obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
# Build PCI Express AER if needed
obj-$(CONFIG_PCIEAER) += aer/
obj-$(CONFIG_PCIE_PME) += pme/
#
# Makefile for PCI-Express Root Port PME signaling driver
#
obj-$(CONFIG_PCIE_PME) += pmedriver.o
pmedriver-objs := pcie_pme.o
pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o
This diff is collapsed.
/*
* drivers/pci/pcie/pme/pcie_pme.h
*
* PCI Express Root Port PME signaling support
*
* Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
*/
#ifndef _PCIE_PME_H_
#define _PCIE_PME_H_
struct pcie_device;
#ifdef CONFIG_ACPI
extern int pcie_pme_acpi_setup(struct pcie_device *srv);
static inline int pcie_pme_platform_notify(struct pcie_device *srv)
{
return pcie_pme_acpi_setup(srv);
}
#else /* !CONFIG_ACPI */
static inline int pcie_pme_platform_notify(struct pcie_device *srv)
{
return 0;
}
#endif /* !CONFIG_ACPI */
#endif
/*
* PCIe Native PME support, ACPI-related part
*
* Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
*
* This file is subject to the terms and conditions of the GNU General Public
* License V2. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/pci-acpi.h>
#include <linux/pcieport_if.h>
/**
* pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME.
* @srv - PCIe PME service for a root port or event collector.
*
* Invoked when the PCIe bus type loads PCIe PME service driver. To avoid
* conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME
* control to the kernel.
*/
int pcie_pme_acpi_setup(struct pcie_device *srv)
{
acpi_status status = AE_NOT_FOUND;
struct pci_dev *port = srv->port;
acpi_handle handle;
int error = 0;
if (acpi_pci_disabled)
return -ENOSYS;
dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n");
handle = acpi_find_root_bridge_handle(port);
if (!handle)
return -EINVAL;
status = acpi_pci_osc_control_set(handle,
OSC_PCI_EXPRESS_PME_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_FAILURE(status)) {
dev_info(&port->dev,
"Failed to receive control of PCIe PME service: %s\n",
(status == AE_SUPPORT || status == AE_NOT_FOUND) ?
"no _OSC support" : "ACPI _OSC failed");
error = -ENODEV;
}
return error;
}
......@@ -266,6 +266,7 @@ struct pci_dev {
configuration space */
unsigned int pme_support:5; /* Bitmask of states from which PME#
can be generated */
unsigned int pme_interrupt:1;
unsigned int d1_support:1; /* Low power state D1 is supported */
unsigned int d2_support:1; /* Low power state D2 is supported */
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment