11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $) 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 121da177e4SLinus Torvalds * your option) any later version. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 151da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 161da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 171da177e4SLinus Torvalds * General Public License for more details. 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 201da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 211da177e4SLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 241da177e4SLinus Torvalds */ 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #include <linux/kernel.h> 271da177e4SLinus Torvalds #include <linux/module.h> 281da177e4SLinus Torvalds #include <linux/init.h> 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/proc_fs.h> 311da177e4SLinus Torvalds #include <linux/spinlock.h> 321da177e4SLinus Torvalds #include <linux/pm.h> 331da177e4SLinus Torvalds #include <linux/pci.h> 34990a7ac5SAndrew Patterson #include <linux/pci-acpi.h> 351da177e4SLinus Torvalds #include <linux/acpi.h> 361da177e4SLinus Torvalds #include <acpi/acpi_bus.h> 371da177e4SLinus Torvalds #include <acpi/acpi_drivers.h> 381da177e4SLinus Torvalds 39a192a958SLen Brown #define PREFIX "ACPI: " 40a192a958SLen Brown 411da177e4SLinus Torvalds #define _COMPONENT ACPI_PCI_COMPONENT 42f52fd66dSLen Brown ACPI_MODULE_NAME("pci_root"); 431da177e4SLinus Torvalds #define ACPI_PCI_ROOT_CLASS "pci_bridge" 441da177e4SLinus Torvalds #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" 451da177e4SLinus Torvalds static int acpi_pci_root_add(struct acpi_device *device); 461da177e4SLinus Torvalds static int acpi_pci_root_remove(struct acpi_device *device, int type); 47c431ada4SRajesh Shah static int acpi_pci_root_start(struct acpi_device *device); 481da177e4SLinus Torvalds 491ba90e3aSThomas Renninger static struct acpi_device_id root_device_ids[] = { 501ba90e3aSThomas Renninger {"PNP0A03", 0}, 511ba90e3aSThomas Renninger {"", 0}, 521ba90e3aSThomas Renninger }; 531ba90e3aSThomas Renninger MODULE_DEVICE_TABLE(acpi, root_device_ids); 541ba90e3aSThomas Renninger 551da177e4SLinus Torvalds static struct acpi_driver acpi_pci_root_driver = { 56c2b6705bSLen Brown .name = "pci_root", 571da177e4SLinus Torvalds .class = ACPI_PCI_ROOT_CLASS, 581ba90e3aSThomas Renninger .ids = root_device_ids, 591da177e4SLinus Torvalds .ops = { 601da177e4SLinus Torvalds .add = acpi_pci_root_add, 611da177e4SLinus Torvalds .remove = acpi_pci_root_remove, 62c431ada4SRajesh Shah .start = acpi_pci_root_start, 631da177e4SLinus Torvalds }, 641da177e4SLinus Torvalds }; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds static LIST_HEAD(acpi_pci_roots); 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds static struct acpi_pci_driver *sub_driver; 6963f10f0fSKenji Kaneshige static DEFINE_MUTEX(osc_lock); 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds int acpi_pci_register_driver(struct acpi_pci_driver *driver) 721da177e4SLinus Torvalds { 731da177e4SLinus Torvalds int n = 0; 74c1aec834SBjorn Helgaas struct acpi_pci_root *root; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds struct acpi_pci_driver **pptr = &sub_driver; 771da177e4SLinus Torvalds while (*pptr) 781da177e4SLinus Torvalds pptr = &(*pptr)->next; 791da177e4SLinus Torvalds *pptr = driver; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds if (!driver->add) 821da177e4SLinus Torvalds return 0; 831da177e4SLinus Torvalds 84c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) { 852d1e0a02SPatrick Mochel driver->add(root->device->handle); 861da177e4SLinus Torvalds n++; 871da177e4SLinus Torvalds } 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds return n; 901da177e4SLinus Torvalds } 914be44fcdSLen Brown 921da177e4SLinus Torvalds EXPORT_SYMBOL(acpi_pci_register_driver); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) 951da177e4SLinus Torvalds { 96c1aec834SBjorn Helgaas struct acpi_pci_root *root; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds struct acpi_pci_driver **pptr = &sub_driver; 991da177e4SLinus Torvalds while (*pptr) { 100f10bb254SAkinobu Mita if (*pptr == driver) 1011da177e4SLinus Torvalds break; 102f10bb254SAkinobu Mita pptr = &(*pptr)->next; 1031da177e4SLinus Torvalds } 104f10bb254SAkinobu Mita BUG_ON(!*pptr); 105f10bb254SAkinobu Mita *pptr = (*pptr)->next; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds if (!driver->remove) 1081da177e4SLinus Torvalds return; 1091da177e4SLinus Torvalds 110c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) 1112d1e0a02SPatrick Mochel driver->remove(root->device->handle); 1121da177e4SLinus Torvalds } 1134be44fcdSLen Brown 1141da177e4SLinus Torvalds EXPORT_SYMBOL(acpi_pci_unregister_driver); 1151da177e4SLinus Torvalds 116d91a0078SJustin Chen acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) 117d91a0078SJustin Chen { 118c1aec834SBjorn Helgaas struct acpi_pci_root *root; 119d91a0078SJustin Chen 120c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) 1210705495dSBjorn Helgaas if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) 122c1aec834SBjorn Helgaas return root->device->handle; 123d91a0078SJustin Chen return NULL; 124d91a0078SJustin Chen } 125d91a0078SJustin Chen 126d91a0078SJustin Chen EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); 127d91a0078SJustin Chen 12827558203SAlexander Chiang /** 12927558203SAlexander Chiang * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge 13027558203SAlexander Chiang * @handle - the ACPI CA node in question. 13127558203SAlexander Chiang * 13227558203SAlexander Chiang * Note: we could make this API take a struct acpi_device * instead, but 13327558203SAlexander Chiang * for now, it's more convenient to operate on an acpi_handle. 13427558203SAlexander Chiang */ 13527558203SAlexander Chiang int acpi_is_root_bridge(acpi_handle handle) 13627558203SAlexander Chiang { 13727558203SAlexander Chiang int ret; 13827558203SAlexander Chiang struct acpi_device *device; 13927558203SAlexander Chiang 14027558203SAlexander Chiang ret = acpi_bus_get_device(handle, &device); 14127558203SAlexander Chiang if (ret) 14227558203SAlexander Chiang return 0; 14327558203SAlexander Chiang 14427558203SAlexander Chiang ret = acpi_match_device_ids(device, root_device_ids); 14527558203SAlexander Chiang if (ret) 14627558203SAlexander Chiang return 0; 14727558203SAlexander Chiang else 14827558203SAlexander Chiang return 1; 14927558203SAlexander Chiang } 15027558203SAlexander Chiang EXPORT_SYMBOL_GPL(acpi_is_root_bridge); 15127558203SAlexander Chiang 1521da177e4SLinus Torvalds static acpi_status 1531da177e4SLinus Torvalds get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) 1541da177e4SLinus Torvalds { 15550dd0969SJan Engelhardt int *busnr = data; 1561da177e4SLinus Torvalds struct acpi_resource_address64 address; 1571da177e4SLinus Torvalds 15850eca3ebSBob Moore if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && 15950eca3ebSBob Moore resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 && 16050eca3ebSBob Moore resource->type != ACPI_RESOURCE_TYPE_ADDRESS64) 1611da177e4SLinus Torvalds return AE_OK; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds acpi_resource_to_address64(resource, &address); 1641da177e4SLinus Torvalds if ((address.address_length > 0) && 1651da177e4SLinus Torvalds (address.resource_type == ACPI_BUS_NUMBER_RANGE)) 16650eca3ebSBob Moore *busnr = address.minimum; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds return AE_OK; 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds 171f5eebbe1SBjorn Helgaas static acpi_status try_get_root_bridge_busnr(acpi_handle handle, 172f5eebbe1SBjorn Helgaas unsigned long long *bus) 1731da177e4SLinus Torvalds { 1741da177e4SLinus Torvalds acpi_status status; 175f5eebbe1SBjorn Helgaas int busnum; 1761da177e4SLinus Torvalds 177f5eebbe1SBjorn Helgaas busnum = -1; 1784be44fcdSLen Brown status = 1794be44fcdSLen Brown acpi_walk_resources(handle, METHOD_NAME__CRS, 180f5eebbe1SBjorn Helgaas get_root_bridge_busnr_callback, &busnum); 1811da177e4SLinus Torvalds if (ACPI_FAILURE(status)) 1821da177e4SLinus Torvalds return status; 1831da177e4SLinus Torvalds /* Check if we really get a bus number from _CRS */ 184f5eebbe1SBjorn Helgaas if (busnum == -1) 1851da177e4SLinus Torvalds return AE_ERROR; 186f5eebbe1SBjorn Helgaas *bus = busnum; 1871da177e4SLinus Torvalds return AE_OK; 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds 1902786f6e3SRui Zhang static void acpi_pci_bridge_scan(struct acpi_device *device) 1912786f6e3SRui Zhang { 1922786f6e3SRui Zhang int status; 1932786f6e3SRui Zhang struct acpi_device *child = NULL; 1942786f6e3SRui Zhang 1952786f6e3SRui Zhang if (device->flags.bus_address) 1962786f6e3SRui Zhang if (device->parent && device->parent->ops.bind) { 1972786f6e3SRui Zhang status = device->parent->ops.bind(device); 1982786f6e3SRui Zhang if (!status) { 1992786f6e3SRui Zhang list_for_each_entry(child, &device->children, node) 2002786f6e3SRui Zhang acpi_pci_bridge_scan(child); 2012786f6e3SRui Zhang } 2022786f6e3SRui Zhang } 2032786f6e3SRui Zhang } 2042786f6e3SRui Zhang 20563f10f0fSKenji Kaneshige static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 20663f10f0fSKenji Kaneshige 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 20763f10f0fSKenji Kaneshige 20863f10f0fSKenji Kaneshige static acpi_status acpi_pci_run_osc(acpi_handle handle, 20963f10f0fSKenji Kaneshige const u32 *capbuf, u32 *retval) 21063f10f0fSKenji Kaneshige { 21163f10f0fSKenji Kaneshige acpi_status status; 21263f10f0fSKenji Kaneshige struct acpi_object_list input; 21363f10f0fSKenji Kaneshige union acpi_object in_params[4]; 21463f10f0fSKenji Kaneshige struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; 21563f10f0fSKenji Kaneshige union acpi_object *out_obj; 21663f10f0fSKenji Kaneshige u32 errors; 21763f10f0fSKenji Kaneshige 21863f10f0fSKenji Kaneshige /* Setting up input parameters */ 21963f10f0fSKenji Kaneshige input.count = 4; 22063f10f0fSKenji Kaneshige input.pointer = in_params; 22163f10f0fSKenji Kaneshige in_params[0].type = ACPI_TYPE_BUFFER; 22263f10f0fSKenji Kaneshige in_params[0].buffer.length = 16; 22363f10f0fSKenji Kaneshige in_params[0].buffer.pointer = OSC_UUID; 22463f10f0fSKenji Kaneshige in_params[1].type = ACPI_TYPE_INTEGER; 22563f10f0fSKenji Kaneshige in_params[1].integer.value = 1; 22663f10f0fSKenji Kaneshige in_params[2].type = ACPI_TYPE_INTEGER; 22763f10f0fSKenji Kaneshige in_params[2].integer.value = 3; 22863f10f0fSKenji Kaneshige in_params[3].type = ACPI_TYPE_BUFFER; 22963f10f0fSKenji Kaneshige in_params[3].buffer.length = 12; 23063f10f0fSKenji Kaneshige in_params[3].buffer.pointer = (u8 *)capbuf; 23163f10f0fSKenji Kaneshige 23263f10f0fSKenji Kaneshige status = acpi_evaluate_object(handle, "_OSC", &input, &output); 23363f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 23463f10f0fSKenji Kaneshige return status; 23563f10f0fSKenji Kaneshige 23663f10f0fSKenji Kaneshige if (!output.length) 23763f10f0fSKenji Kaneshige return AE_NULL_OBJECT; 23863f10f0fSKenji Kaneshige 23963f10f0fSKenji Kaneshige out_obj = output.pointer; 24063f10f0fSKenji Kaneshige if (out_obj->type != ACPI_TYPE_BUFFER) { 24163f10f0fSKenji Kaneshige printk(KERN_DEBUG "_OSC evaluation returned wrong type\n"); 24263f10f0fSKenji Kaneshige status = AE_TYPE; 24363f10f0fSKenji Kaneshige goto out_kfree; 24463f10f0fSKenji Kaneshige } 24563f10f0fSKenji Kaneshige /* Need to ignore the bit0 in result code */ 24663f10f0fSKenji Kaneshige errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); 24763f10f0fSKenji Kaneshige if (errors) { 24863f10f0fSKenji Kaneshige if (errors & OSC_REQUEST_ERROR) 24963f10f0fSKenji Kaneshige printk(KERN_DEBUG "_OSC request failed\n"); 25063f10f0fSKenji Kaneshige if (errors & OSC_INVALID_UUID_ERROR) 25163f10f0fSKenji Kaneshige printk(KERN_DEBUG "_OSC invalid UUID\n"); 25263f10f0fSKenji Kaneshige if (errors & OSC_INVALID_REVISION_ERROR) 25363f10f0fSKenji Kaneshige printk(KERN_DEBUG "_OSC invalid revision\n"); 25463f10f0fSKenji Kaneshige if (errors & OSC_CAPABILITIES_MASK_ERROR) { 25563f10f0fSKenji Kaneshige if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE) 25663f10f0fSKenji Kaneshige goto out_success; 25763f10f0fSKenji Kaneshige printk(KERN_DEBUG 25863f10f0fSKenji Kaneshige "Firmware did not grant requested _OSC control\n"); 25963f10f0fSKenji Kaneshige status = AE_SUPPORT; 26063f10f0fSKenji Kaneshige goto out_kfree; 26163f10f0fSKenji Kaneshige } 26263f10f0fSKenji Kaneshige status = AE_ERROR; 26363f10f0fSKenji Kaneshige goto out_kfree; 26463f10f0fSKenji Kaneshige } 26563f10f0fSKenji Kaneshige out_success: 26663f10f0fSKenji Kaneshige *retval = *((u32 *)(out_obj->buffer.pointer + 8)); 26763f10f0fSKenji Kaneshige status = AE_OK; 26863f10f0fSKenji Kaneshige 26963f10f0fSKenji Kaneshige out_kfree: 27063f10f0fSKenji Kaneshige kfree(output.pointer); 27163f10f0fSKenji Kaneshige return status; 27263f10f0fSKenji Kaneshige } 27363f10f0fSKenji Kaneshige 27463f10f0fSKenji Kaneshige static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) 27563f10f0fSKenji Kaneshige { 27663f10f0fSKenji Kaneshige acpi_status status; 27763f10f0fSKenji Kaneshige u32 support_set, result, capbuf[3]; 27863f10f0fSKenji Kaneshige 27963f10f0fSKenji Kaneshige /* do _OSC query for all possible controls */ 28063f10f0fSKenji Kaneshige support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); 28163f10f0fSKenji Kaneshige capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 28263f10f0fSKenji Kaneshige capbuf[OSC_SUPPORT_TYPE] = support_set; 28363f10f0fSKenji Kaneshige capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 28463f10f0fSKenji Kaneshige 28563f10f0fSKenji Kaneshige status = acpi_pci_run_osc(root->device->handle, capbuf, &result); 28663f10f0fSKenji Kaneshige if (ACPI_SUCCESS(status)) { 28763f10f0fSKenji Kaneshige root->osc_support_set = support_set; 28863f10f0fSKenji Kaneshige root->osc_control_qry = result; 28963f10f0fSKenji Kaneshige root->osc_queried = 1; 29063f10f0fSKenji Kaneshige } 29163f10f0fSKenji Kaneshige return status; 29263f10f0fSKenji Kaneshige } 29363f10f0fSKenji Kaneshige 29463f10f0fSKenji Kaneshige static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) 29563f10f0fSKenji Kaneshige { 29663f10f0fSKenji Kaneshige acpi_status status; 29763f10f0fSKenji Kaneshige acpi_handle tmp; 29863f10f0fSKenji Kaneshige 29963f10f0fSKenji Kaneshige status = acpi_get_handle(root->device->handle, "_OSC", &tmp); 30063f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 30163f10f0fSKenji Kaneshige return status; 30263f10f0fSKenji Kaneshige mutex_lock(&osc_lock); 30363f10f0fSKenji Kaneshige status = acpi_pci_query_osc(root, flags); 30463f10f0fSKenji Kaneshige mutex_unlock(&osc_lock); 30563f10f0fSKenji Kaneshige return status; 30663f10f0fSKenji Kaneshige } 30763f10f0fSKenji Kaneshige 30876d56de5SAlex Chiang struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) 30963f10f0fSKenji Kaneshige { 31063f10f0fSKenji Kaneshige struct acpi_pci_root *root; 311c1aec834SBjorn Helgaas 31263f10f0fSKenji Kaneshige list_for_each_entry(root, &acpi_pci_roots, node) { 31363f10f0fSKenji Kaneshige if (root->device->handle == handle) 31463f10f0fSKenji Kaneshige return root; 31563f10f0fSKenji Kaneshige } 31663f10f0fSKenji Kaneshige return NULL; 31763f10f0fSKenji Kaneshige } 31876d56de5SAlex Chiang EXPORT_SYMBOL_GPL(acpi_pci_find_root); 31963f10f0fSKenji Kaneshige 3202f7bbcebSAlexander Chiang struct acpi_handle_node { 3212f7bbcebSAlexander Chiang struct list_head node; 3222f7bbcebSAlexander Chiang acpi_handle handle; 3232f7bbcebSAlexander Chiang }; 3242f7bbcebSAlexander Chiang 3252f7bbcebSAlexander Chiang /** 3262f7bbcebSAlexander Chiang * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev 3272f7bbcebSAlexander Chiang * @handle: the handle in question 3282f7bbcebSAlexander Chiang * 3292f7bbcebSAlexander Chiang * Given an ACPI CA handle, the desired PCI device is located in the 3302f7bbcebSAlexander Chiang * list of PCI devices. 3312f7bbcebSAlexander Chiang * 3322f7bbcebSAlexander Chiang * If the device is found, its reference count is increased and this 3332f7bbcebSAlexander Chiang * function returns a pointer to its data structure. The caller must 3342f7bbcebSAlexander Chiang * decrement the reference count by calling pci_dev_put(). 3352f7bbcebSAlexander Chiang * If no device is found, %NULL is returned. 3362f7bbcebSAlexander Chiang */ 3372f7bbcebSAlexander Chiang struct pci_dev *acpi_get_pci_dev(acpi_handle handle) 3382f7bbcebSAlexander Chiang { 3392f7bbcebSAlexander Chiang int dev, fn; 3402f7bbcebSAlexander Chiang unsigned long long adr; 3412f7bbcebSAlexander Chiang acpi_status status; 3422f7bbcebSAlexander Chiang acpi_handle phandle; 3432f7bbcebSAlexander Chiang struct pci_bus *pbus; 3442f7bbcebSAlexander Chiang struct pci_dev *pdev = NULL; 3452f7bbcebSAlexander Chiang struct acpi_handle_node *node, *tmp; 3462f7bbcebSAlexander Chiang struct acpi_pci_root *root; 3472f7bbcebSAlexander Chiang LIST_HEAD(device_list); 3482f7bbcebSAlexander Chiang 3492f7bbcebSAlexander Chiang /* 3502f7bbcebSAlexander Chiang * Walk up the ACPI CA namespace until we reach a PCI root bridge. 3512f7bbcebSAlexander Chiang */ 3522f7bbcebSAlexander Chiang phandle = handle; 3532f7bbcebSAlexander Chiang while (!acpi_is_root_bridge(phandle)) { 3542f7bbcebSAlexander Chiang node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); 3552f7bbcebSAlexander Chiang if (!node) 3562f7bbcebSAlexander Chiang goto out; 3572f7bbcebSAlexander Chiang 3582f7bbcebSAlexander Chiang INIT_LIST_HEAD(&node->node); 3592f7bbcebSAlexander Chiang node->handle = phandle; 3602f7bbcebSAlexander Chiang list_add(&node->node, &device_list); 3612f7bbcebSAlexander Chiang 3622f7bbcebSAlexander Chiang status = acpi_get_parent(phandle, &phandle); 3632f7bbcebSAlexander Chiang if (ACPI_FAILURE(status)) 3642f7bbcebSAlexander Chiang goto out; 3652f7bbcebSAlexander Chiang } 3662f7bbcebSAlexander Chiang 3672f7bbcebSAlexander Chiang root = acpi_pci_find_root(phandle); 3682f7bbcebSAlexander Chiang if (!root) 3692f7bbcebSAlexander Chiang goto out; 3702f7bbcebSAlexander Chiang 3712f7bbcebSAlexander Chiang pbus = root->bus; 3722f7bbcebSAlexander Chiang 3732f7bbcebSAlexander Chiang /* 3742f7bbcebSAlexander Chiang * Now, walk back down the PCI device tree until we return to our 3752f7bbcebSAlexander Chiang * original handle. Assumes that everything between the PCI root 3762f7bbcebSAlexander Chiang * bridge and the device we're looking for must be a P2P bridge. 3772f7bbcebSAlexander Chiang */ 3782f7bbcebSAlexander Chiang list_for_each_entry(node, &device_list, node) { 3792f7bbcebSAlexander Chiang acpi_handle hnd = node->handle; 3802f7bbcebSAlexander Chiang status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); 3812f7bbcebSAlexander Chiang if (ACPI_FAILURE(status)) 3822f7bbcebSAlexander Chiang goto out; 3832f7bbcebSAlexander Chiang dev = (adr >> 16) & 0xffff; 3842f7bbcebSAlexander Chiang fn = adr & 0xffff; 3852f7bbcebSAlexander Chiang 3862f7bbcebSAlexander Chiang pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); 387412af978STroy Moure if (!pdev || hnd == handle) 3882f7bbcebSAlexander Chiang break; 3892f7bbcebSAlexander Chiang 3902f7bbcebSAlexander Chiang pbus = pdev->subordinate; 3912f7bbcebSAlexander Chiang pci_dev_put(pdev); 392497fb54fSRafael J. Wysocki 393497fb54fSRafael J. Wysocki /* 394497fb54fSRafael J. Wysocki * This function may be called for a non-PCI device that has a 395497fb54fSRafael J. Wysocki * PCI parent (eg. a disk under a PCI SATA controller). In that 396497fb54fSRafael J. Wysocki * case pdev->subordinate will be NULL for the parent. 397497fb54fSRafael J. Wysocki */ 398497fb54fSRafael J. Wysocki if (!pbus) { 399497fb54fSRafael J. Wysocki dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n"); 400497fb54fSRafael J. Wysocki pdev = NULL; 401497fb54fSRafael J. Wysocki break; 402497fb54fSRafael J. Wysocki } 4032f7bbcebSAlexander Chiang } 4042f7bbcebSAlexander Chiang out: 4052f7bbcebSAlexander Chiang list_for_each_entry_safe(node, tmp, &device_list, node) 4062f7bbcebSAlexander Chiang kfree(node); 4072f7bbcebSAlexander Chiang 4082f7bbcebSAlexander Chiang return pdev; 4092f7bbcebSAlexander Chiang } 4102f7bbcebSAlexander Chiang EXPORT_SYMBOL_GPL(acpi_get_pci_dev); 4112f7bbcebSAlexander Chiang 41263f10f0fSKenji Kaneshige /** 4139f5404d8SKenji Kaneshige * acpi_pci_osc_control_set - commit requested control to Firmware 41463f10f0fSKenji Kaneshige * @handle: acpi_handle for the target ACPI object 41563f10f0fSKenji Kaneshige * @flags: driver's requested control bits 41663f10f0fSKenji Kaneshige * 41763f10f0fSKenji Kaneshige * Attempt to take control from Firmware on requested control bits. 41863f10f0fSKenji Kaneshige **/ 4199f5404d8SKenji Kaneshige acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) 42063f10f0fSKenji Kaneshige { 42163f10f0fSKenji Kaneshige acpi_status status; 42263f10f0fSKenji Kaneshige u32 control_req, result, capbuf[3]; 42363f10f0fSKenji Kaneshige acpi_handle tmp; 42463f10f0fSKenji Kaneshige struct acpi_pci_root *root; 42563f10f0fSKenji Kaneshige 42663f10f0fSKenji Kaneshige status = acpi_get_handle(handle, "_OSC", &tmp); 42763f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 42863f10f0fSKenji Kaneshige return status; 42963f10f0fSKenji Kaneshige 43063f10f0fSKenji Kaneshige control_req = (flags & OSC_CONTROL_MASKS); 43163f10f0fSKenji Kaneshige if (!control_req) 43263f10f0fSKenji Kaneshige return AE_TYPE; 43363f10f0fSKenji Kaneshige 43463f10f0fSKenji Kaneshige root = acpi_pci_find_root(handle); 43563f10f0fSKenji Kaneshige if (!root) 43663f10f0fSKenji Kaneshige return AE_NOT_EXIST; 43763f10f0fSKenji Kaneshige 43863f10f0fSKenji Kaneshige mutex_lock(&osc_lock); 43963f10f0fSKenji Kaneshige /* No need to evaluate _OSC if the control was already granted. */ 44063f10f0fSKenji Kaneshige if ((root->osc_control_set & control_req) == control_req) 44163f10f0fSKenji Kaneshige goto out; 44263f10f0fSKenji Kaneshige 44363f10f0fSKenji Kaneshige /* Need to query controls first before requesting them */ 44463f10f0fSKenji Kaneshige if (!root->osc_queried) { 44563f10f0fSKenji Kaneshige status = acpi_pci_query_osc(root, root->osc_support_set); 44663f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 44763f10f0fSKenji Kaneshige goto out; 44863f10f0fSKenji Kaneshige } 44963f10f0fSKenji Kaneshige if ((root->osc_control_qry & control_req) != control_req) { 45063f10f0fSKenji Kaneshige printk(KERN_DEBUG 45163f10f0fSKenji Kaneshige "Firmware did not grant requested _OSC control\n"); 45263f10f0fSKenji Kaneshige status = AE_SUPPORT; 45363f10f0fSKenji Kaneshige goto out; 45463f10f0fSKenji Kaneshige } 45563f10f0fSKenji Kaneshige 45663f10f0fSKenji Kaneshige capbuf[OSC_QUERY_TYPE] = 0; 45763f10f0fSKenji Kaneshige capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; 45863f10f0fSKenji Kaneshige capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; 45963f10f0fSKenji Kaneshige status = acpi_pci_run_osc(handle, capbuf, &result); 46063f10f0fSKenji Kaneshige if (ACPI_SUCCESS(status)) 46163f10f0fSKenji Kaneshige root->osc_control_set = result; 46263f10f0fSKenji Kaneshige out: 46363f10f0fSKenji Kaneshige mutex_unlock(&osc_lock); 46463f10f0fSKenji Kaneshige return status; 46563f10f0fSKenji Kaneshige } 4669f5404d8SKenji Kaneshige EXPORT_SYMBOL(acpi_pci_osc_control_set); 46763f10f0fSKenji Kaneshige 468b5678a34SSam Ravnborg static int __devinit acpi_pci_root_add(struct acpi_device *device) 4691da177e4SLinus Torvalds { 470f5eebbe1SBjorn Helgaas unsigned long long segment, bus; 471f5eebbe1SBjorn Helgaas acpi_status status; 472f5eebbe1SBjorn Helgaas int result; 473f5eebbe1SBjorn Helgaas struct acpi_pci_root *root; 474f5eebbe1SBjorn Helgaas acpi_handle handle; 4752786f6e3SRui Zhang struct acpi_device *child; 4760ef5f8f6SAndrew Patterson u32 flags, base_flags; 4771da177e4SLinus Torvalds 478f5eebbe1SBjorn Helgaas segment = 0; 479f5eebbe1SBjorn Helgaas status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, 480f5eebbe1SBjorn Helgaas &segment); 481f5eebbe1SBjorn Helgaas if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 482f5eebbe1SBjorn Helgaas printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); 483f5eebbe1SBjorn Helgaas return -ENODEV; 484f5eebbe1SBjorn Helgaas } 4851da177e4SLinus Torvalds 486f5eebbe1SBjorn Helgaas /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ 487f5eebbe1SBjorn Helgaas bus = 0; 488f5eebbe1SBjorn Helgaas status = try_get_root_bridge_busnr(device->handle, &bus); 489f5eebbe1SBjorn Helgaas if (ACPI_FAILURE(status)) { 490f5eebbe1SBjorn Helgaas status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); 491f5eebbe1SBjorn Helgaas if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 492f5eebbe1SBjorn Helgaas printk(KERN_ERR PREFIX 493f5eebbe1SBjorn Helgaas "no bus number in _CRS and can't evaluate _BBN\n"); 494f5eebbe1SBjorn Helgaas return -ENODEV; 495f5eebbe1SBjorn Helgaas } 496f5eebbe1SBjorn Helgaas } 4971da177e4SLinus Torvalds 49836bcbec7SBurman Yan root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); 4991da177e4SLinus Torvalds if (!root) 500d550d98dSPatrick Mochel return -ENOMEM; 5011da177e4SLinus Torvalds 502f5eebbe1SBjorn Helgaas INIT_LIST_HEAD(&root->node); 50332917e5bSPatrick Mochel root->device = device; 5040705495dSBjorn Helgaas root->segment = segment & 0xFFFF; 5050705495dSBjorn Helgaas root->bus_nr = bus & 0xFF; 5061da177e4SLinus Torvalds strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); 5071da177e4SLinus Torvalds strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); 508db89b4f0SPavel Machek device->driver_data = root; 5091da177e4SLinus Torvalds 5101da177e4SLinus Torvalds /* 511990a7ac5SAndrew Patterson * All supported architectures that use ACPI have support for 512990a7ac5SAndrew Patterson * PCI domains, so we indicate this in _OSC support capabilities. 513990a7ac5SAndrew Patterson */ 5140ef5f8f6SAndrew Patterson flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; 51563f10f0fSKenji Kaneshige acpi_pci_osc_support(root, flags); 516990a7ac5SAndrew Patterson 517990a7ac5SAndrew Patterson /* 5181da177e4SLinus Torvalds * TBD: Need PCI interface for enumeration/configuration of roots. 5191da177e4SLinus Torvalds */ 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds /* TBD: Locking */ 5221da177e4SLinus Torvalds list_add_tail(&root->node, &acpi_pci_roots); 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", 5251da177e4SLinus Torvalds acpi_device_name(device), acpi_device_bid(device), 5260705495dSBjorn Helgaas root->segment, root->bus_nr); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds /* 5291da177e4SLinus Torvalds * Scan the Root Bridge 5301da177e4SLinus Torvalds * -------------------- 5311da177e4SLinus Torvalds * Must do this prior to any attempt to bind the root device, as the 5321da177e4SLinus Torvalds * PCI namespace does not get created until this call is made (and 5331da177e4SLinus Torvalds * thus the root bridge's pci_dev does not exist). 5341da177e4SLinus Torvalds */ 5350705495dSBjorn Helgaas root->bus = pci_acpi_scan_root(device, segment, bus); 5361da177e4SLinus Torvalds if (!root->bus) { 5376468463aSLen Brown printk(KERN_ERR PREFIX 5386468463aSLen Brown "Bus %04x:%02x not present in PCI namespace\n", 5390705495dSBjorn Helgaas root->segment, root->bus_nr); 5401da177e4SLinus Torvalds result = -ENODEV; 5411da177e4SLinus Torvalds goto end; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* 5451da177e4SLinus Torvalds * Attach ACPI-PCI Context 5461da177e4SLinus Torvalds * ----------------------- 5471da177e4SLinus Torvalds * Thus binding the ACPI and PCI devices. 5481da177e4SLinus Torvalds */ 549499650deSAlexander Chiang result = acpi_pci_bind_root(device); 5501da177e4SLinus Torvalds if (result) 5511da177e4SLinus Torvalds goto end; 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /* 5541da177e4SLinus Torvalds * PCI Routing Table 5551da177e4SLinus Torvalds * ----------------- 5561da177e4SLinus Torvalds * Evaluate and parse _PRT, if exists. 5571da177e4SLinus Torvalds */ 5582d1e0a02SPatrick Mochel status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); 5591da177e4SLinus Torvalds if (ACPI_SUCCESS(status)) 560859a3f86SAlexander Chiang result = acpi_pci_irq_add_prt(device->handle, root->bus); 5611da177e4SLinus Torvalds 5622786f6e3SRui Zhang /* 5632786f6e3SRui Zhang * Scan and bind all _ADR-Based Devices 5642786f6e3SRui Zhang */ 5652786f6e3SRui Zhang list_for_each_entry(child, &device->children, node) 5662786f6e3SRui Zhang acpi_pci_bridge_scan(child); 5672786f6e3SRui Zhang 5680ef5f8f6SAndrew Patterson /* Indicate support for various _OSC capabilities. */ 5690ef5f8f6SAndrew Patterson if (pci_ext_cfg_avail(root->bus->self)) 5700ef5f8f6SAndrew Patterson flags |= OSC_EXT_PCI_CONFIG_SUPPORT; 5713e1b1600SAndrew Patterson if (pcie_aspm_enabled()) 5723e1b1600SAndrew Patterson flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | 5733e1b1600SAndrew Patterson OSC_CLOCK_PWR_CAPABILITY_SUPPORT; 57407ae95f9SAndrew Patterson if (pci_msi_enabled()) 57507ae95f9SAndrew Patterson flags |= OSC_MSI_SUPPORT; 5760ef5f8f6SAndrew Patterson if (flags != base_flags) 57763f10f0fSKenji Kaneshige acpi_pci_osc_support(root, flags); 5780ef5f8f6SAndrew Patterson 579f5eebbe1SBjorn Helgaas return 0; 580f5eebbe1SBjorn Helgaas 5811da177e4SLinus Torvalds end: 582c431ada4SRajesh Shah if (!list_empty(&root->node)) 583c431ada4SRajesh Shah list_del(&root->node); 5841da177e4SLinus Torvalds kfree(root); 585d550d98dSPatrick Mochel return result; 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 5884be44fcdSLen Brown static int acpi_pci_root_start(struct acpi_device *device) 589c431ada4SRajesh Shah { 590caf420c6SBjorn Helgaas struct acpi_pci_root *root = acpi_driver_data(device); 591c431ada4SRajesh Shah 592c431ada4SRajesh Shah pci_bus_add_devices(root->bus); 593d550d98dSPatrick Mochel return 0; 594c431ada4SRajesh Shah } 5951da177e4SLinus Torvalds 5964be44fcdSLen Brown static int acpi_pci_root_remove(struct acpi_device *device, int type) 5971da177e4SLinus Torvalds { 598caf420c6SBjorn Helgaas struct acpi_pci_root *root = acpi_driver_data(device); 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds kfree(root); 601d550d98dSPatrick Mochel return 0; 6021da177e4SLinus Torvalds } 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds static int __init acpi_pci_root_init(void) 6051da177e4SLinus Torvalds { 6061da177e4SLinus Torvalds if (acpi_pci_disabled) 607d550d98dSPatrick Mochel return 0; 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) 610d550d98dSPatrick Mochel return -ENODEV; 6111da177e4SLinus Torvalds 612d550d98dSPatrick Mochel return 0; 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds subsys_initcall(acpi_pci_root_init); 616