]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/pci/pcie/pme/pcie_pme_acpi.c
ACPI/PCI: Negotiate _OSC control bits before requesting them
[mirror_ubuntu-artful-kernel.git] / drivers / pci / pcie / pme / pcie_pme_acpi.c
1 /*
2 * PCIe Native PME support, ACPI-related part
3 *
4 * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License V2. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11 #include <linux/pci.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/acpi.h>
15 #include <linux/pci-acpi.h>
16 #include <linux/pcieport_if.h>
17
18 /**
19 * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME.
20 * @srv - PCIe PME service for a root port or event collector.
21 *
22 * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid
23 * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME
24 * control to the kernel.
25 */
26 int pcie_pme_acpi_setup(struct pcie_device *srv)
27 {
28 acpi_status status = AE_NOT_FOUND;
29 struct pci_dev *port = srv->port;
30 acpi_handle handle;
31 u32 flags;
32 int error = 0;
33
34 if (acpi_pci_disabled)
35 return -ENOSYS;
36
37 dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n");
38
39 handle = acpi_find_root_bridge_handle(port);
40 if (!handle)
41 return -EINVAL;
42
43 flags = OSC_PCI_EXPRESS_PME_CONTROL |
44 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL;
45
46 status = acpi_pci_osc_control_set(handle, &flags, flags);
47 if (ACPI_FAILURE(status)) {
48 dev_info(&port->dev,
49 "Failed to receive control of PCIe PME service: %s\n",
50 (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
51 "no _OSC support" : "ACPI _OSC failed");
52 error = -ENODEV;
53 }
54
55 return error;
56 }