pme.c revision 271fb719cc472af3b1e96d8c527bb0da7060a172
1c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/*
2c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * PCIe Native PME support
3c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki *
4c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * Copyright (C) 2007 - 2009 Intel Corp
5c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * Copyright (C) 2007 - 2009 Shaohua Li <shaohua.li@intel.com>
6c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
7c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki *
8c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * This file is subject to the terms and conditions of the GNU General Public
9c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * License V2.  See the file "COPYING" in the main directory of this archive
10c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * for more details.
11c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
12c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
13c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/module.h>
14c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/pci.h>
15c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/kernel.h>
16c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/errno.h>
175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
18c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/init.h>
19c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/interrupt.h>
20c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/device.h>
21c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/pcieport_if.h>
22c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/acpi.h>
23c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/pci-acpi.h>
24c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#include <linux/pm_runtime.h>
25c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
26271fb719cc472af3b1e96d8c527bb0da7060a172Rafael J. Wysocki#include "../pci.h"
27271fb719cc472af3b1e96d8c527bb0da7060a172Rafael J. Wysocki#include "portdrv.h"
28c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
29c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#define PCI_EXP_RTSTA_PME	0x10000 /* PME status */
30c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki#define PCI_EXP_RTSTA_PENDING	0x20000 /* PME pending */
31c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
32c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/*
33c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki * If this switch is set, MSI will not be used for PCIe PME signaling.  This
34c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki * causes the PCIe port driver to use INTx interrupts only, but it turns out
35c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based
36c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki * wake-up from system sleep states.
37c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki */
38c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysockibool pcie_pme_msi_disabled;
39c39fae1416d59fd565606793f090cebe3720d50dRafael J. Wysocki
40c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int __init pcie_pme_setup(char *str)
41c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
4228eb5f274a305bf3a13b2c80c4804d4515d05c64Rafael J. Wysocki	if (!strncmp(str, "nomsi", 5))
4328eb5f274a305bf3a13b2c80c4804d4515d05c64Rafael J. Wysocki		pcie_pme_msi_disabled = true;
44b27759f880018b0cd43543dc94c921341b64b5ecRafael J. Wysocki
45c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return 1;
46c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
47c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki__setup("pcie_pme=", pcie_pme_setup);
48c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
49c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistruct pcie_pme_service_data {
50c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spinlock_t lock;
51c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_device *srv;
52c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct work_struct work;
53c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	bool noirq; /* Don't enable the PME interrupt used by this service. */
54c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki};
55c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
56c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
57c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation.
58c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @dev: PCIe root port or event collector.
59c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @enable: Enable or disable the interrupt.
60c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
6128eb5f274a305bf3a13b2c80c4804d4515d05c64Rafael J. Wysockivoid pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
62c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
63c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	int rtctl_pos;
64c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	u16 rtctl;
65c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
66b16694f70c40ea8d539cdc93a422039771e85870Kenji Kaneshige	rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL;
67c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
68c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_read_config_word(dev, rtctl_pos, &rtctl);
69c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (enable)
70c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		rtctl |= PCI_EXP_RTCTL_PMEIE;
71c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	else
72c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		rtctl &= ~PCI_EXP_RTCTL_PMEIE;
73c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_write_config_word(dev, rtctl_pos, rtctl);
74c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
75c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
76c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
77c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_clear_status - Clear root port PME interrupt status.
78c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @dev: PCIe root port or event collector.
79c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
80c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic void pcie_pme_clear_status(struct pci_dev *dev)
81c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
82c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	int rtsta_pos;
83c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	u32 rtsta;
84c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
85b16694f70c40ea8d539cdc93a422039771e85870Kenji Kaneshige	rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;
86c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
87c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_read_config_dword(dev, rtsta_pos, &rtsta);
88c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	rtsta |= PCI_EXP_RTSTA_PME;
89c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_write_config_dword(dev, rtsta_pos, rtsta);
90c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
91c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
92c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
93c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#.
94c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @bus: PCI bus to scan.
95c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki *
96c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * Scan given PCI bus and all buses under it for devices asserting PME#.
97c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
98c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic bool pcie_pme_walk_bus(struct pci_bus *bus)
99c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
100c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *dev;
101c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	bool ret = false;
102c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
103c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	list_for_each_entry(dev, &bus->devices, bus_list) {
104c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		/* Skip PCIe devices in case we started from a root port. */
105552be54cc4232dc5acc49ccb372129d6f1b6923fKenji Kaneshige		if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) {
106c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			pm_request_resume(&dev->dev);
107c125e96f044427f38d106fab7bc5e4a5e6a18262Rafael J. Wysocki			pci_wakeup_event(dev);
108c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			ret = true;
109c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		}
110c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
111c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate))
112c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			ret = true;
113c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
114c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
115c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return ret;
116c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
117c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
118c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
119c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME.
120c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @bus: Secondary bus of the bridge.
121c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @devfn: Device/function number to check.
122c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki *
123c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band
124c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * PCIe PME message.  In such that case the bridge should use the Requester ID
125c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * of device/function number 0 on its secondary bus.
126c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
127c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn)
128c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
129c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *dev;
130c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	bool found = false;
131c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
132c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (devfn)
133c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		return false;
134c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
135c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	dev = pci_dev_get(bus->self);
136c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!dev)
137c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		return false;
138c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
139552be54cc4232dc5acc49ccb372129d6f1b6923fKenji Kaneshige	if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
140c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		down_read(&pci_bus_sem);
141c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (pcie_pme_walk_bus(bus))
142c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			found = true;
143c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		up_read(&pci_bus_sem);
144c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
145c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
146c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_dev_put(dev);
147c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return found;
148c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
149c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
150c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
151c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_handle_request - Find device that generated PME and handle it.
152c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @port: Root port or event collector that generated the PME interrupt.
153c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @req_id: PCIe Requester ID of the device that generated the PME.
154c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
155c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
156c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
157c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	u8 busnr = req_id >> 8, devfn = req_id & 0xff;
158c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_bus *bus;
159c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *dev;
160c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	bool found = false;
161c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
162c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	/* First, check if the PME is from the root port itself. */
163c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (port->devfn == devfn && port->bus->number == busnr) {
164c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (pci_check_pme_status(port)) {
165c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			pm_request_resume(&port->dev);
166c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			found = true;
167c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		} else {
168c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			/*
169c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * Apparently, the root port generated the PME on behalf
170c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * of a non-PCIe device downstream.  If this is done by
171c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * a root port, the Requester ID field in its status
172c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * register may contain either the root port's, or the
173c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * source device's information (PCI Express Base
174c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * Specification, Rev. 2.0, Section 6.1.9).
175c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 */
176c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			down_read(&pci_bus_sem);
177c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			found = pcie_pme_walk_bus(port->subordinate);
178c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			up_read(&pci_bus_sem);
179c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		}
180c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		goto out;
181c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
182c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
183c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	/* Second, find the bus the source device is on. */
184c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	bus = pci_find_bus(pci_domain_nr(port->bus), busnr);
185c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!bus)
186c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		goto out;
187c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
188c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	/* Next, check if the PME is from a PCIe-PCI bridge. */
189c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	found = pcie_pme_from_pci_bridge(bus, devfn);
190c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (found)
191c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		goto out;
192c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
193c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	/* Finally, try to find the PME source on the bus. */
194c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	down_read(&pci_bus_sem);
195c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	list_for_each_entry(dev, &bus->devices, bus_list) {
196c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pci_dev_get(dev);
197c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (dev->devfn == devfn) {
198c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			found = true;
199c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			break;
200c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		}
201c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pci_dev_put(dev);
202c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
203c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	up_read(&pci_bus_sem);
204c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
205c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (found) {
206c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		/* The device is there, but we have to check its PME status. */
207c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		found = pci_check_pme_status(dev);
208c125e96f044427f38d106fab7bc5e4a5e6a18262Rafael J. Wysocki		if (found) {
209c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			pm_request_resume(&dev->dev);
210c125e96f044427f38d106fab7bc5e4a5e6a18262Rafael J. Wysocki			pci_wakeup_event(dev);
211c125e96f044427f38d106fab7bc5e4a5e6a18262Rafael J. Wysocki		}
212c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pci_dev_put(dev);
213c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	} else if (devfn) {
214c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		/*
215c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		 * The device is not there, but we can still try to recover by
216c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		 * assuming that the PME was reported by a PCIe-PCI bridge that
217c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		 * used devfn different from zero.
218c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		 */
219c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		dev_dbg(&port->dev, "PME interrupt generated for "
220c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			"non-existent device %02x:%02x.%d\n",
221c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			busnr, PCI_SLOT(devfn), PCI_FUNC(devfn));
222c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		found = pcie_pme_from_pci_bridge(bus, 0);
223c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
224c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
225c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki out:
226c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!found)
227c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		dev_dbg(&port->dev, "Spurious native PME interrupt!\n");
228c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
229c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
230c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
231c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_work_fn - Work handler for PCIe PME interrupt.
232c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @work: Work structure giving access to service data.
233c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
234c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic void pcie_pme_work_fn(struct work_struct *work)
235c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
236c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_pme_service_data *data =
237c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			container_of(work, struct pcie_pme_service_data, work);
238c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *port = data->srv->port;
239c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	int rtsta_pos;
240c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	u32 rtsta;
241c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
242b16694f70c40ea8d539cdc93a422039771e85870Kenji Kaneshige	rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA;
243c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
244c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_lock_irq(&data->lock);
245c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
246c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	for (;;) {
247c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (data->noirq)
248c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			break;
249c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
250c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pci_read_config_dword(port, rtsta_pos, &rtsta);
251c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (rtsta & PCI_EXP_RTSTA_PME) {
252c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			/*
253c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * Clear PME status of the port.  If there are other
254c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 * pending PMEs, the status will be set again.
255c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			 */
256c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			pcie_pme_clear_status(port);
257c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
258c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			spin_unlock_irq(&data->lock);
259c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			pcie_pme_handle_request(port, rtsta & 0xffff);
260c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			spin_lock_irq(&data->lock);
261c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
262c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			continue;
263c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		}
264c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
265c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		/* No need to loop if there are no more PMEs pending. */
266c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (!(rtsta & PCI_EXP_RTSTA_PENDING))
267c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			break;
268c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
269c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		spin_unlock_irq(&data->lock);
270c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		cpu_relax();
271c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		spin_lock_irq(&data->lock);
272c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
273c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
274c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!data->noirq)
275c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pcie_pme_interrupt_enable(port, true);
276c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
277c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_unlock_irq(&data->lock);
278c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
279c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
280c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
281c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt.
282c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @irq: Interrupt vector.
283c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @context: Interrupt context pointer.
284c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
285c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic irqreturn_t pcie_pme_irq(int irq, void *context)
286c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
287c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *port;
288c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_pme_service_data *data;
289c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	int rtsta_pos;
290c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	u32 rtsta;
291c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	unsigned long flags;
292c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
293c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	port = ((struct pcie_device *)context)->port;
294c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	data = get_service_data((struct pcie_device *)context);
295c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
296b16694f70c40ea8d539cdc93a422039771e85870Kenji Kaneshige	rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA;
297c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
298c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_lock_irqsave(&data->lock, flags);
299c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pci_read_config_dword(port, rtsta_pos, &rtsta);
300c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
301c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!(rtsta & PCI_EXP_RTSTA_PME)) {
302c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		spin_unlock_irqrestore(&data->lock, flags);
303c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		return IRQ_NONE;
304c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
305c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
306c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_interrupt_enable(port, false);
307c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_unlock_irqrestore(&data->lock, flags);
308c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
309c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	/* We don't use pm_wq, because it's freezable. */
310c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	schedule_work(&data->work);
311c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
312c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return IRQ_HANDLED;
313c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
314c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
315c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
316c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_set_native - Set the PME interrupt flag for given device.
317c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @dev: PCI device to handle.
318c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @ign: Ignored.
319c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
320c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int pcie_pme_set_native(struct pci_dev *dev, void *ign)
321c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
322c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	dev_info(&dev->dev, "Signaling PME through PCIe PME interrupt\n");
323c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
324c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	device_set_run_wake(&dev->dev, true);
325c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	dev->pme_interrupt = true;
326c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return 0;
327c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
328c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
329c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
330c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port.
331c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @port: PCIe root port or event collector to handle.
332c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki *
333c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * For each device below given root port, including the port itself (or for each
334c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * root complex integrated endpoint if @port is a root complex event collector)
335c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * set the flag indicating that it can signal run-time wake-up events via PCIe
336c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * PME interrupts.
337c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
338c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic void pcie_pme_mark_devices(struct pci_dev *port)
339c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
340c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_set_native(port, NULL);
341c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (port->subordinate) {
342c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL);
343c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	} else {
344c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		struct pci_bus *bus = port->bus;
345c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		struct pci_dev *dev;
346c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
347c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		/* Check if this is a root port event collector. */
348c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus)
349c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			return;
350c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
351c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		down_read(&pci_bus_sem);
352c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		list_for_each_entry(dev, &bus->devices, bus_list)
353552be54cc4232dc5acc49ccb372129d6f1b6923fKenji Kaneshige			if (pci_is_pcie(dev)
354c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki			    && dev->pcie_type == PCI_EXP_TYPE_RC_END)
355c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki				pcie_pme_set_native(dev, NULL);
356c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		up_read(&pci_bus_sem);
357c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
358c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
359c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
360c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
361c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_probe - Initialize PCIe PME service for given root port.
362c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @srv: PCIe service to initialize.
363c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
364c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int pcie_pme_probe(struct pcie_device *srv)
365c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
366c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *port;
367c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_pme_service_data *data;
368c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	int ret;
369c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
370c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	data = kzalloc(sizeof(*data), GFP_KERNEL);
371c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (!data)
372c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		return -ENOMEM;
373c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
374c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_lock_init(&data->lock);
375c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	INIT_WORK(&data->work, pcie_pme_work_fn);
376c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	data->srv = srv;
377c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	set_service_data(srv, data);
378c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
379c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	port = srv->port;
380c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_interrupt_enable(port, false);
381c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_clear_status(port);
382c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
383c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv);
384c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	if (ret) {
385c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		kfree(data);
386c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	} else {
387c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pcie_pme_mark_devices(port);
388c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki		pcie_pme_interrupt_enable(port, true);
389c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	}
390c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
391c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return ret;
392c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
393c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
394c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
395c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_suspend - Suspend PCIe PME service device.
396c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @srv: PCIe service device to suspend.
397c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
398c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int pcie_pme_suspend(struct pcie_device *srv)
399c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
400c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_pme_service_data *data = get_service_data(srv);
401c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *port = srv->port;
402c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
403c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_lock_irq(&data->lock);
404c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_interrupt_enable(port, false);
405c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_clear_status(port);
406c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	data->noirq = true;
407c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_unlock_irq(&data->lock);
408c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
409c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	synchronize_irq(srv->irq);
410c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
411c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return 0;
412c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
413c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
414c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
415c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_resume - Resume PCIe PME service device.
416c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @srv - PCIe service device to resume.
417c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
418c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int pcie_pme_resume(struct pcie_device *srv)
419c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
420c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pcie_pme_service_data *data = get_service_data(srv);
421c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	struct pci_dev *port = srv->port;
422c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
423c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_lock_irq(&data->lock);
424c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	data->noirq = false;
425c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_clear_status(port);
426c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_interrupt_enable(port, true);
427c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	spin_unlock_irq(&data->lock);
428c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
429c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	return 0;
430c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
431c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
432c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
433c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_remove - Prepare PCIe PME service device for removal.
434c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * @srv - PCIe service device to resume.
435c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
436c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic void pcie_pme_remove(struct pcie_device *srv)
437c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
438c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	pcie_pme_suspend(srv);
439c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	free_irq(srv->irq, srv);
440c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	kfree(get_service_data(srv));
441c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
442c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
443c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic struct pcie_port_service_driver pcie_pme_driver = {
444c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.name		= "pcie_pme",
445c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.port_type 	= PCI_EXP_TYPE_ROOT_PORT,
446c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.service 	= PCIE_PORT_SERVICE_PME,
447c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
448c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.probe		= pcie_pme_probe,
449c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.suspend	= pcie_pme_suspend,
450c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.resume		= pcie_pme_resume,
451c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki	.remove		= pcie_pme_remove,
452c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki};
453c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
454c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki/**
455c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki * pcie_pme_service_init - Register the PCIe PME service driver.
456c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki */
457c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockistatic int __init pcie_pme_service_init(void)
458c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki{
45928eb5f274a305bf3a13b2c80c4804d4515d05c64Rafael J. Wysocki	return pcie_port_service_register(&pcie_pme_driver);
460c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki}
461c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysocki
462c7f486567c1d0acd2e4166c47069835b9f75e77bRafael J. Wysockimodule_init(pcie_pme_service_init);
463