linux/arch/x86/pci/acpi.c
<<
>>
Prefs
   1#include <linux/pci.h>
   2#include <linux/acpi.h>
   3#include <linux/init.h>
   4#include <linux/irq.h>
   5#include <linux/dmi.h>
   6#include <asm/numa.h>
   7#include <asm/pci_x86.h>
   8
   9struct pci_root_info {
  10        char *name;
  11        unsigned int res_num;
  12        struct resource *res;
  13        struct pci_bus *bus;
  14        int busnum;
  15};
  16
  17static acpi_status
  18resource_to_addr(struct acpi_resource *resource,
  19                        struct acpi_resource_address64 *addr)
  20{
  21        acpi_status status;
  22
  23        status = acpi_resource_to_address64(resource, addr);
  24        if (ACPI_SUCCESS(status) &&
  25            (addr->resource_type == ACPI_MEMORY_RANGE ||
  26            addr->resource_type == ACPI_IO_RANGE) &&
  27            addr->address_length > 0 &&
  28            addr->producer_consumer == ACPI_PRODUCER) {
  29                return AE_OK;
  30        }
  31        return AE_ERROR;
  32}
  33
  34static acpi_status
  35count_resource(struct acpi_resource *acpi_res, void *data)
  36{
  37        struct pci_root_info *info = data;
  38        struct acpi_resource_address64 addr;
  39        acpi_status status;
  40
  41        status = resource_to_addr(acpi_res, &addr);
  42        if (ACPI_SUCCESS(status))
  43                info->res_num++;
  44        return AE_OK;
  45}
  46
  47static int
  48bus_has_transparent_bridge(struct pci_bus *bus)
  49{
  50        struct pci_dev *dev;
  51
  52        list_for_each_entry(dev, &bus->devices, bus_list) {
  53                u16 class = dev->class >> 8;
  54
  55                if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
  56                        return true;
  57        }
  58        return false;
  59}
  60
  61static acpi_status
  62setup_resource(struct acpi_resource *acpi_res, void *data)
  63{
  64        struct pci_root_info *info = data;
  65        struct resource *res;
  66        struct acpi_resource_address64 addr;
  67        acpi_status status;
  68        unsigned long flags;
  69        struct resource *root;
  70        int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
  71        u64 start, end;
  72
  73        if (bus_has_transparent_bridge(info->bus))
  74                max_root_bus_resources -= 3;
  75
  76        status = resource_to_addr(acpi_res, &addr);
  77        if (!ACPI_SUCCESS(status))
  78                return AE_OK;
  79
  80        if (addr.resource_type == ACPI_MEMORY_RANGE) {
  81                root = &iomem_resource;
  82                flags = IORESOURCE_MEM;
  83                if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
  84                        flags |= IORESOURCE_PREFETCH;
  85        } else if (addr.resource_type == ACPI_IO_RANGE) {
  86                root = &ioport_resource;
  87                flags = IORESOURCE_IO;
  88        } else
  89                return AE_OK;
  90
  91        start = addr.minimum + addr.translation_offset;
  92        end = start + addr.address_length - 1;
  93        if (info->res_num >= max_root_bus_resources) {
  94                printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
  95                        "from %s for %s due to _CRS returning more than "
  96                        "%d resource descriptors\n", (unsigned long) start,
  97                        (unsigned long) end, root->name, info->name,
  98                        max_root_bus_resources);
  99                return AE_OK;
 100        }
 101
 102        res = &info->res[info->res_num];
 103        res->name = info->name;
 104        res->flags = flags;
 105        res->start = start;
 106        res->end = end;
 107        res->child = NULL;
 108
 109        if (insert_resource(root, res)) {
 110                printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
 111                        "from %s for %s\n", (unsigned long) res->start,
 112                        (unsigned long) res->end, root->name, info->name);
 113        } else {
 114                info->bus->resource[info->res_num] = res;
 115                info->res_num++;
 116        }
 117        return AE_OK;
 118}
 119
 120static void
 121get_current_resources(struct acpi_device *device, int busnum,
 122                        int domain, struct pci_bus *bus)
 123{
 124        struct pci_root_info info;
 125        size_t size;
 126
 127        info.bus = bus;
 128        info.res_num = 0;
 129        acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
 130                                &info);
 131        if (!info.res_num)
 132                return;
 133
 134        size = sizeof(*info.res) * info.res_num;
 135        info.res = kmalloc(size, GFP_KERNEL);
 136        if (!info.res)
 137                goto res_alloc_fail;
 138
 139        info.name = kmalloc(16, GFP_KERNEL);
 140        if (!info.name)
 141                goto name_alloc_fail;
 142        sprintf(info.name, "PCI Bus %04x:%02x", domain, busnum);
 143
 144        info.res_num = 0;
 145        acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 146                                &info);
 147
 148        return;
 149
 150name_alloc_fail:
 151        kfree(info.res);
 152res_alloc_fail:
 153        return;
 154}
 155
 156struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 157{
 158        struct pci_bus *bus;
 159        struct pci_sysdata *sd;
 160        int node;
 161#ifdef CONFIG_ACPI_NUMA
 162        int pxm;
 163#endif
 164
 165        if (domain && !pci_domains_supported) {
 166                printk(KERN_WARNING "PCI: Multiple domains not supported "
 167                       "(dom %d, bus %d)\n", domain, busnum);
 168                return NULL;
 169        }
 170
 171        node = -1;
 172#ifdef CONFIG_ACPI_NUMA
 173        pxm = acpi_get_pxm(device->handle);
 174        if (pxm >= 0)
 175                node = pxm_to_node(pxm);
 176        if (node != -1)
 177                set_mp_bus_to_node(busnum, node);
 178        else
 179#endif
 180                node = get_mp_bus_to_node(busnum);
 181
 182        if (node != -1 && !node_online(node))
 183                node = -1;
 184
 185        /* Allocate per-root-bus (not per bus) arch-specific data.
 186         * TODO: leak; this memory is never freed.
 187         * It's arguable whether it's worth the trouble to care.
 188         */
 189        sd = kzalloc(sizeof(*sd), GFP_KERNEL);
 190        if (!sd) {
 191                printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
 192                return NULL;
 193        }
 194
 195        sd->domain = domain;
 196        sd->node = node;
 197        /*
 198         * Maybe the desired pci bus has been already scanned. In such case
 199         * it is unnecessary to scan the pci bus with the given domain,busnum.
 200         */
 201        bus = pci_find_bus(domain, busnum);
 202        if (bus) {
 203                /*
 204                 * If the desired bus exits, the content of bus->sysdata will
 205                 * be replaced by sd.
 206                 */
 207                memcpy(bus->sysdata, sd, sizeof(*sd));
 208                kfree(sd);
 209        } else {
 210                bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
 211                if (bus) {
 212                        if (pci_probe & PCI_USE__CRS)
 213                                get_current_resources(device, busnum, domain,
 214                                                        bus);
 215                        bus->subordinate = pci_scan_child_bus(bus);
 216                }
 217        }
 218
 219        if (!bus)
 220                kfree(sd);
 221
 222        if (bus && node != -1) {
 223#ifdef CONFIG_ACPI_NUMA
 224                if (pxm >= 0)
 225                        dev_printk(KERN_DEBUG, &bus->dev,
 226                                   "on NUMA node %d (pxm %d)\n", node, pxm);
 227#else
 228                dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
 229#endif
 230        }
 231
 232        return bus;
 233}
 234
 235int __init pci_acpi_init(void)
 236{
 237        struct pci_dev *dev = NULL;
 238
 239        if (pcibios_scanned)
 240                return 0;
 241
 242        if (acpi_noirq)
 243                return 0;
 244
 245        printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
 246        acpi_irq_penalty_init();
 247        pcibios_scanned++;
 248        pcibios_enable_irq = acpi_pci_irq_enable;
 249        pcibios_disable_irq = acpi_pci_irq_disable;
 250
 251        if (pci_routeirq) {
 252                /*
 253                 * PCI IRQ routing is set up by pci_enable_device(), but we
 254                 * also do it here in case there are still broken drivers that
 255                 * don't use pci_enable_device().
 256                 */
 257                printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
 258                for_each_pci_dev(dev)
 259                        acpi_pci_irq_enable(dev);
 260        }
 261
 262        return 0;
 263}
 264