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