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