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