Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bus_numa.c
Go to the documentation of this file.
1 #include <linux/init.h>
2 #include <linux/pci.h>
3 #include <linux/range.h>
4 
5 #include "bus_numa.h"
6 
7 LIST_HEAD(pci_root_infos);
8 
9 static 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 
24 {
25  struct pci_root_info *info = x86_find_pci_root_info(bus);
26  struct pci_root_res *root_res;
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 
60 default_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 
71 struct 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 
92 
93  return info;
94 }
95 
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 
133 addit:
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 }