linux/arch/x86/pci/bus_numa.c
<<
>>
Prefs
   1#include <linux/init.h>
   2#include <linux/pci.h>
   3#include <linux/range.h>
   4
   5#include "bus_numa.h"
   6
   7LIST_HEAD(pci_root_infos);
   8
   9static struct pci_root_info *x86_find_pci_root_info(int bus)
  10{
  11        struct pci_root_info *info;
  12
  13        if (list_empty(&pci_root_infos))
  14                return NULL;
  15
  16        list_for_each_entry(info, &pci_root_infos, list)
  17                if (info->busn.start == bus)
  18                        return info;
  19
  20        return NULL;
  21}
  22
  23void x86_pci_root_bus_resources(int bus, struct list_head *resources)
  24{
  25        struct pci_root_info *info = x86_find_pci_root_info(bus);
  26        struct pci_root_res *root_res;
  27        struct pci_host_bridge_window *window;
  28        bool found = false;
  29
  30        if (!info)
  31                goto default_resources;
  32
  33        printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
  34               bus);
  35
  36        /* already added by acpi ? */
  37        list_for_each_entry(window, resources, list)
  38                if (window->res->flags & IORESOURCE_BUS) {
  39                        found = true;
  40                        break;
  41                }
  42
  43        if (!found)
  44                pci_add_resource(resources, &info->busn);
  45
  46        list_for_each_entry(root_res, &info->resources, list) {
  47                struct resource *res;
  48                struct resource *root;
  49
  50                res = &root_res->res;
  51                pci_add_resource(resources, res);
  52                if (res->flags & IORESOURCE_IO)
  53                        root = &ioport_resource;
  54                else
  55                        root = &iomem_resource;
  56                insert_resource(root, res);
  57        }
  58        return;
  59
  60default_resources:
  61        /*
  62         * We don't have any host bridge aperture information from the
  63         * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
  64         * so fall back to the defaults historically used by pci_create_bus().
  65         */
  66        printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
  67        pci_add_resource(resources, &ioport_resource);
  68        pci_add_resource(resources, &iomem_resource);
  69}
  70
  71struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
  72                                                 int node, int link)
  73{
  74        struct pci_root_info *info;
  75
  76        info = kzalloc(sizeof(*info), GFP_KERNEL);
  77
  78        if (!info)
  79                return info;
  80
  81        sprintf(info->name, "PCI Bus #%02x", bus_min);
  82
  83        INIT_LIST_HEAD(&info->resources);
  84        info->busn.name  = info->name;
  85        info->busn.start = bus_min;
  86        info->busn.end   = bus_max;
  87        info->busn.flags = IORESOURCE_BUS;
  88        info->node = node;
  89        info->link = link;
  90
  91        list_add_tail(&info->list, &pci_root_infos);
  92
  93        return info;
  94}
  95
  96void update_res(struct pci_root_info *info, resource_size_t start,
  97                resource_size_t end, unsigned long flags, int merge)
  98{
  99        struct resource *res;
 100        struct pci_root_res *root_res;
 101
 102        if (start > end)
 103                return;
 104
 105        if (start == MAX_RESOURCE)
 106                return;
 107
 108        if (!merge)
 109                goto addit;
 110
 111        /* try to merge it with old one */
 112        list_for_each_entry(root_res, &info->resources, list) {
 113                resource_size_t final_start, final_end;
 114                resource_size_t common_start, common_end;
 115
 116                res = &root_res->res;
 117                if (res->flags != flags)
 118                        continue;
 119
 120                common_start = max(res->start, start);
 121                common_end = min(res->end, end);
 122                if (common_start > common_end + 1)
 123                        continue;
 124
 125                final_start = min(res->start, start);
 126                final_end = max(res->end, end);
 127
 128                res->start = final_start;
 129                res->end = final_end;
 130                return;
 131        }
 132
 133addit:
 134
 135        /* need to add that */
 136        root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
 137        if (!root_res)
 138                return;
 139
 140        res = &root_res->res;
 141        res->name = info->name;
 142        res->flags = flags;
 143        res->start = start;
 144        res->end = end;
 145
 146        list_add_tail(&root_res->list, &info->resources);
 147}
 148