55 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			55 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * PCIe Native PME support, ACPI-related part | ||
|  |  * | ||
|  |  * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
|  |  * | ||
|  |  * This file is subject to the terms and conditions of the GNU General Public | ||
|  |  * License V2.  See the file "COPYING" in the main directory of this archive | ||
|  |  * for more details. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <linux/pci.h>
 | ||
|  | #include <linux/kernel.h>
 | ||
|  | #include <linux/errno.h>
 | ||
|  | #include <linux/acpi.h>
 | ||
|  | #include <linux/pci-acpi.h>
 | ||
|  | #include <linux/pcieport_if.h>
 | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. | ||
|  |  * @srv - PCIe PME service for a root port or event collector. | ||
|  |  * | ||
|  |  * Invoked when the PCIe bus type loads PCIe PME service driver.  To avoid | ||
|  |  * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME | ||
|  |  * control to the kernel. | ||
|  |  */ | ||
|  | int pcie_pme_acpi_setup(struct pcie_device *srv) | ||
|  | { | ||
|  | 	acpi_status status = AE_NOT_FOUND; | ||
|  | 	struct pci_dev *port = srv->port; | ||
|  | 	acpi_handle handle; | ||
|  | 	int error = 0; | ||
|  | 
 | ||
|  | 	if (acpi_pci_disabled) | ||
|  | 		return -ENOSYS; | ||
|  | 
 | ||
|  | 	dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); | ||
|  | 
 | ||
|  | 	handle = acpi_find_root_bridge_handle(port); | ||
|  | 	if (!handle) | ||
|  | 		return -EINVAL; | ||
|  | 
 | ||
|  | 	status = acpi_pci_osc_control_set(handle, | ||
|  | 			OSC_PCI_EXPRESS_PME_CONTROL | | ||
|  | 			OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
|  | 	if (ACPI_FAILURE(status)) { | ||
|  | 		dev_info(&port->dev, | ||
|  | 			"Failed to receive control of PCIe PME service: %s\n", | ||
|  | 			(status == AE_SUPPORT || status == AE_NOT_FOUND) ? | ||
|  | 			"no _OSC support" : "ACPI _OSC failed"); | ||
|  | 		error = -ENODEV; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return error; | ||
|  | } |