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> 30d0020f65STaku Izumi #include <linux/mutex.h> 311da177e4SLinus Torvalds #include <linux/pm.h> 32b67ea761SRafael J. Wysocki #include <linux/pm_runtime.h> 331da177e4SLinus Torvalds #include <linux/pci.h> 34990a7ac5SAndrew Patterson #include <linux/pci-acpi.h> 35eca67315SNaga Chumbalkar #include <linux/pci-aspm.h> 361da177e4SLinus Torvalds #include <linux/acpi.h> 375a0e3ad6STejun Heo #include <linux/slab.h> 381da177e4SLinus Torvalds #include <acpi/acpi_bus.h> 391da177e4SLinus Torvalds #include <acpi/acpi_drivers.h> 40415e12b2SRafael J. Wysocki #include <acpi/apei.h> 411da177e4SLinus Torvalds 42a192a958SLen Brown #define PREFIX "ACPI: " 43a192a958SLen Brown 441da177e4SLinus Torvalds #define _COMPONENT ACPI_PCI_COMPONENT 45f52fd66dSLen Brown ACPI_MODULE_NAME("pci_root"); 461da177e4SLinus Torvalds #define ACPI_PCI_ROOT_CLASS "pci_bridge" 471da177e4SLinus Torvalds #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" 4800c43b96SRafael J. Wysocki static int acpi_pci_root_add(struct acpi_device *device, 4900c43b96SRafael J. Wysocki const struct acpi_device_id *not_used); 5000c43b96SRafael J. Wysocki static void acpi_pci_root_remove(struct acpi_device *device); 511da177e4SLinus Torvalds 52415e12b2SRafael J. Wysocki #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ 53415e12b2SRafael J. Wysocki | OSC_ACTIVE_STATE_PWR_SUPPORT \ 54415e12b2SRafael J. Wysocki | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ 55415e12b2SRafael J. Wysocki | OSC_MSI_SUPPORT) 56415e12b2SRafael J. Wysocki 57c97adf9eSMárton Németh static const struct acpi_device_id root_device_ids[] = { 581ba90e3aSThomas Renninger {"PNP0A03", 0}, 591ba90e3aSThomas Renninger {"", 0}, 601ba90e3aSThomas Renninger }; 611ba90e3aSThomas Renninger 6200c43b96SRafael J. Wysocki static struct acpi_scan_handler pci_root_handler = { 631ba90e3aSThomas Renninger .ids = root_device_ids, 6400c43b96SRafael J. Wysocki .attach = acpi_pci_root_add, 6500c43b96SRafael J. Wysocki .detach = acpi_pci_root_remove, 661da177e4SLinus Torvalds }; 671da177e4SLinus Torvalds 68d0020f65STaku Izumi /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ 69d0020f65STaku Izumi static DEFINE_MUTEX(acpi_pci_root_lock); 701da177e4SLinus Torvalds static LIST_HEAD(acpi_pci_roots); 718ee5bdf3SJiang Liu static LIST_HEAD(acpi_pci_drivers); 721da177e4SLinus Torvalds 7363f10f0fSKenji Kaneshige static DEFINE_MUTEX(osc_lock); 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds int acpi_pci_register_driver(struct acpi_pci_driver *driver) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds int n = 0; 78c1aec834SBjorn Helgaas struct acpi_pci_root *root; 791da177e4SLinus Torvalds 80d0020f65STaku Izumi mutex_lock(&acpi_pci_root_lock); 818ee5bdf3SJiang Liu list_add_tail(&driver->node, &acpi_pci_drivers); 82d0020f65STaku Izumi if (driver->add) 83c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) { 8455bfe3c0STaku Izumi driver->add(root); 851da177e4SLinus Torvalds n++; 861da177e4SLinus Torvalds } 87d0020f65STaku Izumi mutex_unlock(&acpi_pci_root_lock); 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds return n; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds EXPORT_SYMBOL(acpi_pci_register_driver); 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) 941da177e4SLinus Torvalds { 95c1aec834SBjorn Helgaas struct acpi_pci_root *root; 961da177e4SLinus Torvalds 97d0020f65STaku Izumi mutex_lock(&acpi_pci_root_lock); 988ee5bdf3SJiang Liu list_del(&driver->node); 99d0020f65STaku Izumi if (driver->remove) 100c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) 10155bfe3c0STaku Izumi driver->remove(root); 102d0020f65STaku Izumi mutex_unlock(&acpi_pci_root_lock); 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds EXPORT_SYMBOL(acpi_pci_unregister_driver); 1051da177e4SLinus Torvalds 106d91a0078SJustin Chen acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) 107d91a0078SJustin Chen { 108c1aec834SBjorn Helgaas struct acpi_pci_root *root; 1096507e6ebSTaku Izumi acpi_handle handle = NULL; 110d91a0078SJustin Chen 1116507e6ebSTaku Izumi mutex_lock(&acpi_pci_root_lock); 112c1aec834SBjorn Helgaas list_for_each_entry(root, &acpi_pci_roots, node) 1136ad95513SBjorn Helgaas if ((root->segment == (u16) seg) && 1146507e6ebSTaku Izumi (root->secondary.start == (u16) bus)) { 1156507e6ebSTaku Izumi handle = root->device->handle; 1166507e6ebSTaku Izumi break; 1176507e6ebSTaku Izumi } 1186507e6ebSTaku Izumi mutex_unlock(&acpi_pci_root_lock); 1196507e6ebSTaku Izumi return handle; 120d91a0078SJustin Chen } 121d91a0078SJustin Chen 122d91a0078SJustin Chen EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); 123d91a0078SJustin Chen 12427558203SAlexander Chiang /** 12527558203SAlexander Chiang * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge 12627558203SAlexander Chiang * @handle - the ACPI CA node in question. 12727558203SAlexander Chiang * 12827558203SAlexander Chiang * Note: we could make this API take a struct acpi_device * instead, but 12927558203SAlexander Chiang * for now, it's more convenient to operate on an acpi_handle. 13027558203SAlexander Chiang */ 13127558203SAlexander Chiang int acpi_is_root_bridge(acpi_handle handle) 13227558203SAlexander Chiang { 13327558203SAlexander Chiang int ret; 13427558203SAlexander Chiang struct acpi_device *device; 13527558203SAlexander Chiang 13627558203SAlexander Chiang ret = acpi_bus_get_device(handle, &device); 13727558203SAlexander Chiang if (ret) 13827558203SAlexander Chiang return 0; 13927558203SAlexander Chiang 14027558203SAlexander Chiang ret = acpi_match_device_ids(device, root_device_ids); 14127558203SAlexander Chiang if (ret) 14227558203SAlexander Chiang return 0; 14327558203SAlexander Chiang else 14427558203SAlexander Chiang return 1; 14527558203SAlexander Chiang } 14627558203SAlexander Chiang EXPORT_SYMBOL_GPL(acpi_is_root_bridge); 14727558203SAlexander Chiang 1481da177e4SLinus Torvalds static acpi_status 1491da177e4SLinus Torvalds get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) 1501da177e4SLinus Torvalds { 1516ad95513SBjorn Helgaas struct resource *res = data; 1521da177e4SLinus Torvalds struct acpi_resource_address64 address; 1531da177e4SLinus Torvalds 15450eca3ebSBob Moore if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && 15550eca3ebSBob Moore resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 && 15650eca3ebSBob Moore resource->type != ACPI_RESOURCE_TYPE_ADDRESS64) 1571da177e4SLinus Torvalds return AE_OK; 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds acpi_resource_to_address64(resource, &address); 1601da177e4SLinus Torvalds if ((address.address_length > 0) && 1616ad95513SBjorn Helgaas (address.resource_type == ACPI_BUS_NUMBER_RANGE)) { 1626ad95513SBjorn Helgaas res->start = address.minimum; 1636ad95513SBjorn Helgaas res->end = address.minimum + address.address_length - 1; 1646ad95513SBjorn Helgaas } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds return AE_OK; 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 169f5eebbe1SBjorn Helgaas static acpi_status try_get_root_bridge_busnr(acpi_handle handle, 1706ad95513SBjorn Helgaas struct resource *res) 1711da177e4SLinus Torvalds { 1721da177e4SLinus Torvalds acpi_status status; 1731da177e4SLinus Torvalds 1746ad95513SBjorn Helgaas res->start = -1; 1754be44fcdSLen Brown status = 1764be44fcdSLen Brown acpi_walk_resources(handle, METHOD_NAME__CRS, 1776ad95513SBjorn Helgaas get_root_bridge_busnr_callback, res); 1781da177e4SLinus Torvalds if (ACPI_FAILURE(status)) 1791da177e4SLinus Torvalds return status; 1806ad95513SBjorn Helgaas if (res->start == -1) 1811da177e4SLinus Torvalds return AE_ERROR; 1821da177e4SLinus Torvalds return AE_OK; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1853a9622dcSShaohua Li static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; 18663f10f0fSKenji Kaneshige 18763f10f0fSKenji Kaneshige static acpi_status acpi_pci_run_osc(acpi_handle handle, 18863f10f0fSKenji Kaneshige const u32 *capbuf, u32 *retval) 18963f10f0fSKenji Kaneshige { 1903a9622dcSShaohua Li struct acpi_osc_context context = { 1913a9622dcSShaohua Li .uuid_str = pci_osc_uuid_str, 1923a9622dcSShaohua Li .rev = 1, 1933a9622dcSShaohua Li .cap.length = 12, 1943a9622dcSShaohua Li .cap.pointer = (void *)capbuf, 1953a9622dcSShaohua Li }; 19663f10f0fSKenji Kaneshige acpi_status status; 19763f10f0fSKenji Kaneshige 1983a9622dcSShaohua Li status = acpi_run_osc(handle, &context); 1993a9622dcSShaohua Li if (ACPI_SUCCESS(status)) { 2003a9622dcSShaohua Li *retval = *((u32 *)(context.ret.pointer + 8)); 2013a9622dcSShaohua Li kfree(context.ret.pointer); 20263f10f0fSKenji Kaneshige } 20363f10f0fSKenji Kaneshige return status; 20463f10f0fSKenji Kaneshige } 20563f10f0fSKenji Kaneshige 206ab8e8957SRafael J. Wysocki static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, 207ab8e8957SRafael J. Wysocki u32 support, 208ab8e8957SRafael J. Wysocki u32 *control) 20963f10f0fSKenji Kaneshige { 21063f10f0fSKenji Kaneshige acpi_status status; 211ab8e8957SRafael J. Wysocki u32 result, capbuf[3]; 21263f10f0fSKenji Kaneshige 213ab8e8957SRafael J. Wysocki support &= OSC_PCI_SUPPORT_MASKS; 214ab8e8957SRafael J. Wysocki support |= root->osc_support_set; 215ab8e8957SRafael J. Wysocki 21663f10f0fSKenji Kaneshige capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 217ab8e8957SRafael J. Wysocki capbuf[OSC_SUPPORT_TYPE] = support; 218ab8e8957SRafael J. Wysocki if (control) { 219ab8e8957SRafael J. Wysocki *control &= OSC_PCI_CONTROL_MASKS; 220ab8e8957SRafael J. Wysocki capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; 221ab8e8957SRafael J. Wysocki } else { 222ab8e8957SRafael J. Wysocki /* Run _OSC query for all possible controls. */ 2233a9622dcSShaohua Li capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; 224ab8e8957SRafael J. Wysocki } 22563f10f0fSKenji Kaneshige 22663f10f0fSKenji Kaneshige status = acpi_pci_run_osc(root->device->handle, capbuf, &result); 22763f10f0fSKenji Kaneshige if (ACPI_SUCCESS(status)) { 228ab8e8957SRafael J. Wysocki root->osc_support_set = support; 2292b8fd918SRafael J. Wysocki if (control) 230ab8e8957SRafael J. Wysocki *control = result; 231ab8e8957SRafael J. Wysocki } 23263f10f0fSKenji Kaneshige return status; 23363f10f0fSKenji Kaneshige } 23463f10f0fSKenji Kaneshige 23563f10f0fSKenji Kaneshige static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) 23663f10f0fSKenji Kaneshige { 23763f10f0fSKenji Kaneshige acpi_status status; 23863f10f0fSKenji Kaneshige acpi_handle tmp; 23963f10f0fSKenji Kaneshige 24063f10f0fSKenji Kaneshige status = acpi_get_handle(root->device->handle, "_OSC", &tmp); 24163f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 24263f10f0fSKenji Kaneshige return status; 24363f10f0fSKenji Kaneshige mutex_lock(&osc_lock); 244ab8e8957SRafael J. Wysocki status = acpi_pci_query_osc(root, flags, NULL); 24563f10f0fSKenji Kaneshige mutex_unlock(&osc_lock); 24663f10f0fSKenji Kaneshige return status; 24763f10f0fSKenji Kaneshige } 24863f10f0fSKenji Kaneshige 24976d56de5SAlex Chiang struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) 25063f10f0fSKenji Kaneshige { 25163f10f0fSKenji Kaneshige struct acpi_pci_root *root; 252cd4faf9cSTaku Izumi struct acpi_device *device; 253c1aec834SBjorn Helgaas 254cd4faf9cSTaku Izumi if (acpi_bus_get_device(handle, &device) || 255cd4faf9cSTaku Izumi acpi_match_device_ids(device, root_device_ids)) 25663f10f0fSKenji Kaneshige return NULL; 257cd4faf9cSTaku Izumi 258cd4faf9cSTaku Izumi root = acpi_driver_data(device); 259cd4faf9cSTaku Izumi 260cd4faf9cSTaku Izumi return root; 26163f10f0fSKenji Kaneshige } 26276d56de5SAlex Chiang EXPORT_SYMBOL_GPL(acpi_pci_find_root); 26363f10f0fSKenji Kaneshige 2642f7bbcebSAlexander Chiang struct acpi_handle_node { 2652f7bbcebSAlexander Chiang struct list_head node; 2662f7bbcebSAlexander Chiang acpi_handle handle; 2672f7bbcebSAlexander Chiang }; 2682f7bbcebSAlexander Chiang 2692f7bbcebSAlexander Chiang /** 2702f7bbcebSAlexander Chiang * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev 2712f7bbcebSAlexander Chiang * @handle: the handle in question 2722f7bbcebSAlexander Chiang * 2732f7bbcebSAlexander Chiang * Given an ACPI CA handle, the desired PCI device is located in the 2742f7bbcebSAlexander Chiang * list of PCI devices. 2752f7bbcebSAlexander Chiang * 2762f7bbcebSAlexander Chiang * If the device is found, its reference count is increased and this 2772f7bbcebSAlexander Chiang * function returns a pointer to its data structure. The caller must 2782f7bbcebSAlexander Chiang * decrement the reference count by calling pci_dev_put(). 2792f7bbcebSAlexander Chiang * If no device is found, %NULL is returned. 2802f7bbcebSAlexander Chiang */ 2812f7bbcebSAlexander Chiang struct pci_dev *acpi_get_pci_dev(acpi_handle handle) 2822f7bbcebSAlexander Chiang { 2832f7bbcebSAlexander Chiang int dev, fn; 2842f7bbcebSAlexander Chiang unsigned long long adr; 2852f7bbcebSAlexander Chiang acpi_status status; 2862f7bbcebSAlexander Chiang acpi_handle phandle; 2872f7bbcebSAlexander Chiang struct pci_bus *pbus; 2882f7bbcebSAlexander Chiang struct pci_dev *pdev = NULL; 2892f7bbcebSAlexander Chiang struct acpi_handle_node *node, *tmp; 2902f7bbcebSAlexander Chiang struct acpi_pci_root *root; 2912f7bbcebSAlexander Chiang LIST_HEAD(device_list); 2922f7bbcebSAlexander Chiang 2932f7bbcebSAlexander Chiang /* 2942f7bbcebSAlexander Chiang * Walk up the ACPI CA namespace until we reach a PCI root bridge. 2952f7bbcebSAlexander Chiang */ 2962f7bbcebSAlexander Chiang phandle = handle; 2972f7bbcebSAlexander Chiang while (!acpi_is_root_bridge(phandle)) { 2982f7bbcebSAlexander Chiang node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); 2992f7bbcebSAlexander Chiang if (!node) 3002f7bbcebSAlexander Chiang goto out; 3012f7bbcebSAlexander Chiang 3022f7bbcebSAlexander Chiang INIT_LIST_HEAD(&node->node); 3032f7bbcebSAlexander Chiang node->handle = phandle; 3042f7bbcebSAlexander Chiang list_add(&node->node, &device_list); 3052f7bbcebSAlexander Chiang 3062f7bbcebSAlexander Chiang status = acpi_get_parent(phandle, &phandle); 3072f7bbcebSAlexander Chiang if (ACPI_FAILURE(status)) 3082f7bbcebSAlexander Chiang goto out; 3092f7bbcebSAlexander Chiang } 3102f7bbcebSAlexander Chiang 3112f7bbcebSAlexander Chiang root = acpi_pci_find_root(phandle); 3122f7bbcebSAlexander Chiang if (!root) 3132f7bbcebSAlexander Chiang goto out; 3142f7bbcebSAlexander Chiang 3152f7bbcebSAlexander Chiang pbus = root->bus; 3162f7bbcebSAlexander Chiang 3172f7bbcebSAlexander Chiang /* 3182f7bbcebSAlexander Chiang * Now, walk back down the PCI device tree until we return to our 3192f7bbcebSAlexander Chiang * original handle. Assumes that everything between the PCI root 3202f7bbcebSAlexander Chiang * bridge and the device we're looking for must be a P2P bridge. 3212f7bbcebSAlexander Chiang */ 3222f7bbcebSAlexander Chiang list_for_each_entry(node, &device_list, node) { 3232f7bbcebSAlexander Chiang acpi_handle hnd = node->handle; 3242f7bbcebSAlexander Chiang status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); 3252f7bbcebSAlexander Chiang if (ACPI_FAILURE(status)) 3262f7bbcebSAlexander Chiang goto out; 3272f7bbcebSAlexander Chiang dev = (adr >> 16) & 0xffff; 3282f7bbcebSAlexander Chiang fn = adr & 0xffff; 3292f7bbcebSAlexander Chiang 3302f7bbcebSAlexander Chiang pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); 331412af978STroy Moure if (!pdev || hnd == handle) 3322f7bbcebSAlexander Chiang break; 3332f7bbcebSAlexander Chiang 3342f7bbcebSAlexander Chiang pbus = pdev->subordinate; 3352f7bbcebSAlexander Chiang pci_dev_put(pdev); 336497fb54fSRafael J. Wysocki 337497fb54fSRafael J. Wysocki /* 338497fb54fSRafael J. Wysocki * This function may be called for a non-PCI device that has a 339497fb54fSRafael J. Wysocki * PCI parent (eg. a disk under a PCI SATA controller). In that 340497fb54fSRafael J. Wysocki * case pdev->subordinate will be NULL for the parent. 341497fb54fSRafael J. Wysocki */ 342497fb54fSRafael J. Wysocki if (!pbus) { 343497fb54fSRafael J. Wysocki dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n"); 344497fb54fSRafael J. Wysocki pdev = NULL; 345497fb54fSRafael J. Wysocki break; 346497fb54fSRafael J. Wysocki } 3472f7bbcebSAlexander Chiang } 3482f7bbcebSAlexander Chiang out: 3492f7bbcebSAlexander Chiang list_for_each_entry_safe(node, tmp, &device_list, node) 3502f7bbcebSAlexander Chiang kfree(node); 3512f7bbcebSAlexander Chiang 3522f7bbcebSAlexander Chiang return pdev; 3532f7bbcebSAlexander Chiang } 3542f7bbcebSAlexander Chiang EXPORT_SYMBOL_GPL(acpi_get_pci_dev); 3552f7bbcebSAlexander Chiang 35663f10f0fSKenji Kaneshige /** 35775fb60f2SRafael J. Wysocki * acpi_pci_osc_control_set - Request control of PCI root _OSC features. 35875fb60f2SRafael J. Wysocki * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). 35975fb60f2SRafael J. Wysocki * @mask: Mask of _OSC bits to request control of, place to store control mask. 36075fb60f2SRafael J. Wysocki * @req: Mask of _OSC bits the control of is essential to the caller. 36163f10f0fSKenji Kaneshige * 36275fb60f2SRafael J. Wysocki * Run _OSC query for @mask and if that is successful, compare the returned 36375fb60f2SRafael J. Wysocki * mask of control bits with @req. If all of the @req bits are set in the 36475fb60f2SRafael J. Wysocki * returned mask, run _OSC request for it. 36575fb60f2SRafael J. Wysocki * 36675fb60f2SRafael J. Wysocki * The variable at the @mask address may be modified regardless of whether or 36775fb60f2SRafael J. Wysocki * not the function returns success. On success it will contain the mask of 36875fb60f2SRafael J. Wysocki * _OSC bits the BIOS has granted control of, but its contents are meaningless 36975fb60f2SRafael J. Wysocki * on failure. 37063f10f0fSKenji Kaneshige **/ 37175fb60f2SRafael J. Wysocki acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) 37263f10f0fSKenji Kaneshige { 37363f10f0fSKenji Kaneshige struct acpi_pci_root *root; 37475fb60f2SRafael J. Wysocki acpi_status status; 37575fb60f2SRafael J. Wysocki u32 ctrl, capbuf[3]; 37675fb60f2SRafael J. Wysocki acpi_handle tmp; 37763f10f0fSKenji Kaneshige 37875fb60f2SRafael J. Wysocki if (!mask) 37975fb60f2SRafael J. Wysocki return AE_BAD_PARAMETER; 38075fb60f2SRafael J. Wysocki 38175fb60f2SRafael J. Wysocki ctrl = *mask & OSC_PCI_CONTROL_MASKS; 38275fb60f2SRafael J. Wysocki if ((ctrl & req) != req) 38363f10f0fSKenji Kaneshige return AE_TYPE; 38463f10f0fSKenji Kaneshige 38563f10f0fSKenji Kaneshige root = acpi_pci_find_root(handle); 38663f10f0fSKenji Kaneshige if (!root) 38763f10f0fSKenji Kaneshige return AE_NOT_EXIST; 38863f10f0fSKenji Kaneshige 389b879dc4bSRafael J. Wysocki status = acpi_get_handle(handle, "_OSC", &tmp); 390b879dc4bSRafael J. Wysocki if (ACPI_FAILURE(status)) 391b879dc4bSRafael J. Wysocki return status; 392b879dc4bSRafael J. Wysocki 39363f10f0fSKenji Kaneshige mutex_lock(&osc_lock); 39475fb60f2SRafael J. Wysocki 39575fb60f2SRafael J. Wysocki *mask = ctrl | root->osc_control_set; 39663f10f0fSKenji Kaneshige /* No need to evaluate _OSC if the control was already granted. */ 39775fb60f2SRafael J. Wysocki if ((root->osc_control_set & ctrl) == ctrl) 39863f10f0fSKenji Kaneshige goto out; 39963f10f0fSKenji Kaneshige 40075fb60f2SRafael J. Wysocki /* Need to check the available controls bits before requesting them. */ 40175fb60f2SRafael J. Wysocki while (*mask) { 40275fb60f2SRafael J. Wysocki status = acpi_pci_query_osc(root, root->osc_support_set, mask); 40363f10f0fSKenji Kaneshige if (ACPI_FAILURE(status)) 40463f10f0fSKenji Kaneshige goto out; 40575fb60f2SRafael J. Wysocki if (ctrl == *mask) 40675fb60f2SRafael J. Wysocki break; 40775fb60f2SRafael J. Wysocki ctrl = *mask; 40875fb60f2SRafael J. Wysocki } 4092b8fd918SRafael J. Wysocki 41075fb60f2SRafael J. Wysocki if ((ctrl & req) != req) { 41163f10f0fSKenji Kaneshige status = AE_SUPPORT; 41263f10f0fSKenji Kaneshige goto out; 41363f10f0fSKenji Kaneshige } 41463f10f0fSKenji Kaneshige 41563f10f0fSKenji Kaneshige capbuf[OSC_QUERY_TYPE] = 0; 41663f10f0fSKenji Kaneshige capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; 41775fb60f2SRafael J. Wysocki capbuf[OSC_CONTROL_TYPE] = ctrl; 41875fb60f2SRafael J. Wysocki status = acpi_pci_run_osc(handle, capbuf, mask); 41963f10f0fSKenji Kaneshige if (ACPI_SUCCESS(status)) 42075fb60f2SRafael J. Wysocki root->osc_control_set = *mask; 42163f10f0fSKenji Kaneshige out: 42263f10f0fSKenji Kaneshige mutex_unlock(&osc_lock); 42363f10f0fSKenji Kaneshige return status; 42463f10f0fSKenji Kaneshige } 4259f5404d8SKenji Kaneshige EXPORT_SYMBOL(acpi_pci_osc_control_set); 42663f10f0fSKenji Kaneshige 42700c43b96SRafael J. Wysocki static int acpi_pci_root_add(struct acpi_device *device, 42800c43b96SRafael J. Wysocki const struct acpi_device_id *not_used) 4291da177e4SLinus Torvalds { 430f5eebbe1SBjorn Helgaas unsigned long long segment, bus; 431f5eebbe1SBjorn Helgaas acpi_status status; 432f5eebbe1SBjorn Helgaas int result; 433f5eebbe1SBjorn Helgaas struct acpi_pci_root *root; 434f5eebbe1SBjorn Helgaas acpi_handle handle; 43547525cdaSRafael J. Wysocki struct acpi_pci_driver *driver; 4360ef5f8f6SAndrew Patterson u32 flags, base_flags; 4378c33f51dSTaku Izumi bool is_osc_granted = false; 4381da177e4SLinus Torvalds 4396ad95513SBjorn Helgaas root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); 4406ad95513SBjorn Helgaas if (!root) 4416ad95513SBjorn Helgaas return -ENOMEM; 4426ad95513SBjorn Helgaas 443f5eebbe1SBjorn Helgaas segment = 0; 444f5eebbe1SBjorn Helgaas status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, 445f5eebbe1SBjorn Helgaas &segment); 446f5eebbe1SBjorn Helgaas if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 447f5eebbe1SBjorn Helgaas printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); 4486ad95513SBjorn Helgaas result = -ENODEV; 4496ad95513SBjorn Helgaas goto end; 450f5eebbe1SBjorn Helgaas } 4511da177e4SLinus Torvalds 452f5eebbe1SBjorn Helgaas /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ 4536ad95513SBjorn Helgaas root->secondary.flags = IORESOURCE_BUS; 4546ad95513SBjorn Helgaas status = try_get_root_bridge_busnr(device->handle, &root->secondary); 455f5eebbe1SBjorn Helgaas if (ACPI_FAILURE(status)) { 4566ad95513SBjorn Helgaas /* 4576ad95513SBjorn Helgaas * We need both the start and end of the downstream bus range 4586ad95513SBjorn Helgaas * to interpret _CBA (MMCONFIG base address), so it really is 4596ad95513SBjorn Helgaas * supposed to be in _CRS. If we don't find it there, all we 4606ad95513SBjorn Helgaas * can do is assume [_BBN-0xFF] or [0-0xFF]. 4616ad95513SBjorn Helgaas */ 4626ad95513SBjorn Helgaas root->secondary.end = 0xFF; 4636ad95513SBjorn Helgaas printk(KERN_WARNING FW_BUG PREFIX 4646ad95513SBjorn Helgaas "no secondary bus range in _CRS\n"); 465e545b55aSJon Mason status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, 466e545b55aSJon Mason NULL, &bus); 4676ad95513SBjorn Helgaas if (ACPI_SUCCESS(status)) 4686ad95513SBjorn Helgaas root->secondary.start = bus; 4696ad95513SBjorn Helgaas else if (status == AE_NOT_FOUND) 4706ad95513SBjorn Helgaas root->secondary.start = 0; 4716ad95513SBjorn Helgaas else { 4726ad95513SBjorn Helgaas printk(KERN_ERR PREFIX "can't evaluate _BBN\n"); 4736ad95513SBjorn Helgaas result = -ENODEV; 4746ad95513SBjorn Helgaas goto end; 475f5eebbe1SBjorn Helgaas } 476f5eebbe1SBjorn Helgaas } 4771da177e4SLinus Torvalds 478f5eebbe1SBjorn Helgaas INIT_LIST_HEAD(&root->node); 47932917e5bSPatrick Mochel root->device = device; 4800705495dSBjorn Helgaas root->segment = segment & 0xFFFF; 4811da177e4SLinus Torvalds strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); 4821da177e4SLinus Torvalds strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); 483db89b4f0SPavel Machek device->driver_data = root; 4841da177e4SLinus Torvalds 485d4761ba2SBjorn Helgaas printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", 486d4761ba2SBjorn Helgaas acpi_device_name(device), acpi_device_bid(device), 487d4761ba2SBjorn Helgaas root->segment, &root->secondary); 488d4761ba2SBjorn Helgaas 489d4761ba2SBjorn Helgaas /* 490d4761ba2SBjorn Helgaas * PCI Routing Table 491d4761ba2SBjorn Helgaas * ----------------- 492d4761ba2SBjorn Helgaas * Evaluate and parse _PRT, if exists. 493d4761ba2SBjorn Helgaas */ 494d4761ba2SBjorn Helgaas status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); 495d4761ba2SBjorn Helgaas if (ACPI_SUCCESS(status)) 496d4761ba2SBjorn Helgaas result = acpi_pci_irq_add_prt(device->handle, root->segment, 497d4761ba2SBjorn Helgaas root->secondary.start); 498d4761ba2SBjorn Helgaas 499f4b57a3bSJiang Liu root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); 500f4b57a3bSJiang Liu 5011da177e4SLinus Torvalds /* 502990a7ac5SAndrew Patterson * All supported architectures that use ACPI have support for 503990a7ac5SAndrew Patterson * PCI domains, so we indicate this in _OSC support capabilities. 504990a7ac5SAndrew Patterson */ 5050ef5f8f6SAndrew Patterson flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; 50663f10f0fSKenji Kaneshige acpi_pci_osc_support(root, flags); 507990a7ac5SAndrew Patterson 5088c33f51dSTaku Izumi /* Indicate support for various _OSC capabilities. */ 5098c33f51dSTaku Izumi if (pci_ext_cfg_avail()) 5108c33f51dSTaku Izumi flags |= OSC_EXT_PCI_CONFIG_SUPPORT; 5118c33f51dSTaku Izumi if (pcie_aspm_support_enabled()) { 5128c33f51dSTaku Izumi flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | 5138c33f51dSTaku Izumi OSC_CLOCK_PWR_CAPABILITY_SUPPORT; 5148c33f51dSTaku Izumi } 5158c33f51dSTaku Izumi if (pci_msi_enabled()) 5168c33f51dSTaku Izumi flags |= OSC_MSI_SUPPORT; 5178c33f51dSTaku Izumi if (flags != base_flags) { 5188c33f51dSTaku Izumi status = acpi_pci_osc_support(root, flags); 5198c33f51dSTaku Izumi if (ACPI_FAILURE(status)) { 5208c33f51dSTaku Izumi dev_info(&device->dev, "ACPI _OSC support " 5218c33f51dSTaku Izumi "notification failed, disabling PCIe ASPM\n"); 5228c33f51dSTaku Izumi pcie_no_aspm(); 5238c33f51dSTaku Izumi flags = base_flags; 5248c33f51dSTaku Izumi } 5258c33f51dSTaku Izumi } 5268c33f51dSTaku Izumi if (!pcie_ports_disabled 5278c33f51dSTaku Izumi && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { 5288c33f51dSTaku Izumi flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 5298c33f51dSTaku Izumi | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 5308c33f51dSTaku Izumi | OSC_PCI_EXPRESS_PME_CONTROL; 5318c33f51dSTaku Izumi 5328c33f51dSTaku Izumi if (pci_aer_available()) { 5338c33f51dSTaku Izumi if (aer_acpi_firmware_first()) 5348c33f51dSTaku Izumi dev_dbg(&device->dev, 5358c33f51dSTaku Izumi "PCIe errors handled by BIOS.\n"); 5368c33f51dSTaku Izumi else 5378c33f51dSTaku Izumi flags |= OSC_PCI_EXPRESS_AER_CONTROL; 5388c33f51dSTaku Izumi } 5398c33f51dSTaku Izumi 5408c33f51dSTaku Izumi dev_info(&device->dev, 5418c33f51dSTaku Izumi "Requesting ACPI _OSC control (0x%02x)\n", flags); 5428c33f51dSTaku Izumi 5438c33f51dSTaku Izumi status = acpi_pci_osc_control_set(device->handle, &flags, 5448c33f51dSTaku Izumi OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); 5458c33f51dSTaku Izumi if (ACPI_SUCCESS(status)) { 5468c33f51dSTaku Izumi is_osc_granted = true; 5478c33f51dSTaku Izumi dev_info(&device->dev, 5488c33f51dSTaku Izumi "ACPI _OSC control (0x%02x) granted\n", flags); 5498c33f51dSTaku Izumi } else { 5508c33f51dSTaku Izumi is_osc_granted = false; 5518c33f51dSTaku Izumi dev_info(&device->dev, 5528c33f51dSTaku Izumi "ACPI _OSC request failed (%s), " 5538c33f51dSTaku Izumi "returned control mask: 0x%02x\n", 5548c33f51dSTaku Izumi acpi_format_exception(status), flags); 5558c33f51dSTaku Izumi } 5568c33f51dSTaku Izumi } else { 5578c33f51dSTaku Izumi dev_info(&device->dev, 5588c33f51dSTaku Izumi "Unable to request _OSC control " 5598c33f51dSTaku Izumi "(_OSC support mask: 0x%02x)\n", flags); 5608c33f51dSTaku Izumi } 5618c33f51dSTaku Izumi 562990a7ac5SAndrew Patterson /* 5631da177e4SLinus Torvalds * TBD: Need PCI interface for enumeration/configuration of roots. 5641da177e4SLinus Torvalds */ 5651da177e4SLinus Torvalds 5666507e6ebSTaku Izumi mutex_lock(&acpi_pci_root_lock); 5671da177e4SLinus Torvalds list_add_tail(&root->node, &acpi_pci_roots); 5686507e6ebSTaku Izumi mutex_unlock(&acpi_pci_root_lock); 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds /* 5711da177e4SLinus Torvalds * Scan the Root Bridge 5721da177e4SLinus Torvalds * -------------------- 5731da177e4SLinus Torvalds * Must do this prior to any attempt to bind the root device, as the 5741da177e4SLinus Torvalds * PCI namespace does not get created until this call is made (and 5751da177e4SLinus Torvalds * thus the root bridge's pci_dev does not exist). 5761da177e4SLinus Torvalds */ 57757283776SBjorn Helgaas root->bus = pci_acpi_scan_root(root); 5781da177e4SLinus Torvalds if (!root->bus) { 5796468463aSLen Brown printk(KERN_ERR PREFIX 5806468463aSLen Brown "Bus %04x:%02x not present in PCI namespace\n", 5816ad95513SBjorn Helgaas root->segment, (unsigned int)root->secondary.start); 5821da177e4SLinus Torvalds result = -ENODEV; 5836507e6ebSTaku Izumi goto out_del_root; 5841da177e4SLinus Torvalds } 5851da177e4SLinus Torvalds 5868c33f51dSTaku Izumi /* ASPM setting */ 5878c33f51dSTaku Izumi if (is_osc_granted) { 5888c33f51dSTaku Izumi if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) 5893c076351SMatthew Garrett pcie_clear_aspm(root->bus); 590eca67315SNaga Chumbalkar } else { 591a246670dSRafael J. Wysocki pr_info("ACPI _OSC control for PCIe not granted, " 592a246670dSRafael J. Wysocki "disabling ASPM\n"); 593eca67315SNaga Chumbalkar pcie_no_aspm(); 594eca67315SNaga Chumbalkar } 595415e12b2SRafael J. Wysocki 596b67ea761SRafael J. Wysocki pci_acpi_add_bus_pm_notifier(device, root->bus); 597b67ea761SRafael J. Wysocki if (device->wakeup.flags.run_wake) 598b67ea761SRafael J. Wysocki device_set_run_wake(root->bus->bridge, true); 599b67ea761SRafael J. Wysocki 60062a08c5aSYinghai Lu if (system_state != SYSTEM_BOOTING) 60162a08c5aSYinghai Lu pci_assign_unassigned_bus_resources(root->bus); 60262a08c5aSYinghai Lu 603d0020f65STaku Izumi mutex_lock(&acpi_pci_root_lock); 604c8e9afb1SJiang Liu list_for_each_entry(driver, &acpi_pci_drivers, node) 605c8e9afb1SJiang Liu if (driver->add) 60655bfe3c0STaku Izumi driver->add(root); 607d0020f65STaku Izumi mutex_unlock(&acpi_pci_root_lock); 608c431ada4SRajesh Shah 60962a08c5aSYinghai Lu /* need to after hot-added ioapic is registered */ 61062a08c5aSYinghai Lu if (system_state != SYSTEM_BOOTING) 61162a08c5aSYinghai Lu pci_enable_bridges(root->bus); 61262a08c5aSYinghai Lu 613c431ada4SRajesh Shah pci_bus_add_devices(root->bus); 61400c43b96SRafael J. Wysocki return 1; 61547525cdaSRafael J. Wysocki 61647525cdaSRafael J. Wysocki out_del_root: 61747525cdaSRafael J. Wysocki mutex_lock(&acpi_pci_root_lock); 61847525cdaSRafael J. Wysocki list_del(&root->node); 61947525cdaSRafael J. Wysocki mutex_unlock(&acpi_pci_root_lock); 62047525cdaSRafael J. Wysocki 62147525cdaSRafael J. Wysocki acpi_pci_irq_del_prt(root->segment, root->secondary.start); 62247525cdaSRafael J. Wysocki end: 62347525cdaSRafael J. Wysocki kfree(root); 62447525cdaSRafael J. Wysocki return result; 625c431ada4SRajesh Shah } 6261da177e4SLinus Torvalds 62700c43b96SRafael J. Wysocki static void acpi_pci_root_remove(struct acpi_device *device) 6281da177e4SLinus Torvalds { 62913b6a916SYinghai Lu acpi_status status; 63013b6a916SYinghai Lu acpi_handle handle; 631caf420c6SBjorn Helgaas struct acpi_pci_root *root = acpi_driver_data(device); 632c8e9afb1SJiang Liu struct acpi_pci_driver *driver; 633c8e9afb1SJiang Liu 6349738a1fdSYinghai Lu pci_stop_root_bus(root->bus); 6359738a1fdSYinghai Lu 636d0020f65STaku Izumi mutex_lock(&acpi_pci_root_lock); 637f426cef3SYinghai Lu list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) 638c8e9afb1SJiang Liu if (driver->remove) 63955bfe3c0STaku Izumi driver->remove(root); 6409738a1fdSYinghai Lu mutex_unlock(&acpi_pci_root_lock); 6411da177e4SLinus Torvalds 642b67ea761SRafael J. Wysocki device_set_run_wake(root->bus->bridge, false); 643b67ea761SRafael J. Wysocki pci_acpi_remove_bus_pm_notifier(device); 644b67ea761SRafael J. Wysocki 64513b6a916SYinghai Lu status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); 64613b6a916SYinghai Lu if (ACPI_SUCCESS(status)) 64779c44122SBjorn Helgaas acpi_pci_irq_del_prt(root->segment, root->secondary.start); 64813b6a916SYinghai Lu 6499738a1fdSYinghai Lu pci_remove_root_bus(root->bus); 6509738a1fdSYinghai Lu 6519738a1fdSYinghai Lu mutex_lock(&acpi_pci_root_lock); 6526507e6ebSTaku Izumi list_del(&root->node); 6536507e6ebSTaku Izumi mutex_unlock(&acpi_pci_root_lock); 6541da177e4SLinus Torvalds kfree(root); 6551da177e4SLinus Torvalds } 6561da177e4SLinus Torvalds 65700c43b96SRafael J. Wysocki void __init acpi_pci_root_init(void) 6581da177e4SLinus Torvalds { 659d3072e6aSRafael J. Wysocki acpi_hest_init(); 660d3072e6aSRafael J. Wysocki 66100c43b96SRafael J. Wysocki if (!acpi_pci_disabled) { 6627bc5e3f2SBjorn Helgaas pci_acpi_crs_quirks(); 66300c43b96SRafael J. Wysocki acpi_scan_add_handler(&pci_root_handler); 66400c43b96SRafael J. Wysocki } 6651da177e4SLinus Torvalds } 666