aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-04-02 21:31:54 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-04-30 16:52:43 -0400
commitd28e5ac2a07e27638cf5ac061721b7969e17fe78 (patch)
tree4ae91ae8d95f3ef23d8fa9be5f1d02b8cdc53715 /arch/x86/pci
parent35cb05e5bdac209cfdfafbe50d89ee7069cb6237 (diff)
x86/PCI: dynamically allocate pci_root_info for native host bridge drivers
This dynamically allocates struct pci_root_info instead of using a static array. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/amd_bus.c76
-rw-r--r--arch/x86/pci/broadcom_bus.c12
-rw-r--r--arch/x86/pci/bus_numa.c69
-rw-r--r--arch/x86/pci/bus_numa.h18
4 files changed, 88 insertions, 87 deletions
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0567df3890e1..459a7316375c 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -32,6 +32,18 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
32 32
33#define RANGE_NUM 16 33#define RANGE_NUM 16
34 34
35static struct pci_root_info __init *find_pci_root_info(int node, int link)
36{
37 struct pci_root_info *info;
38
39 /* find the position */
40 list_for_each_entry(info, &pci_root_infos, list)
41 if (info->node == node && info->link == link)
42 return info;
43
44 return NULL;
45}
46
35/** 47/**
36 * early_fill_mp_bus_to_node() 48 * early_fill_mp_bus_to_node()
37 * called before pcibios_scan_root and pci_scan_bus 49 * called before pcibios_scan_root and pci_scan_bus
@@ -50,7 +62,6 @@ static int __init early_fill_mp_bus_info(void)
50 int def_link; 62 int def_link;
51 struct pci_root_info *info; 63 struct pci_root_info *info;
52 u32 reg; 64 u32 reg;
53 struct resource *res;
54 u64 start; 65 u64 start;
55 u64 end; 66 u64 end;
56 struct range range[RANGE_NUM]; 67 struct range range[RANGE_NUM];
@@ -86,7 +97,6 @@ static int __init early_fill_mp_bus_info(void)
86 if (!found) 97 if (!found)
87 return 0; 98 return 0;
88 99
89 pci_root_num = 0;
90 for (i = 0; i < 4; i++) { 100 for (i = 0; i < 4; i++) {
91 int min_bus; 101 int min_bus;
92 int max_bus; 102 int max_bus;
@@ -105,13 +115,8 @@ static int __init early_fill_mp_bus_info(void)
105#endif 115#endif
106 link = (reg >> 8) & 0x03; 116 link = (reg >> 8) & 0x03;
107 117
108 info = &pci_root_info[pci_root_num]; 118 info = alloc_pci_root_info(min_bus, max_bus, node, link);
109 info->bus_min = min_bus;
110 info->bus_max = max_bus;
111 info->node = node;
112 info->link = link;
113 sprintf(info->name, "PCI Bus #%02x", min_bus); 119 sprintf(info->name, "PCI Bus #%02x", min_bus);
114 pci_root_num++;
115 } 120 }
116 121
117 /* get the default node and link for left over res */ 122 /* get the default node and link for left over res */
@@ -134,16 +139,10 @@ static int __init early_fill_mp_bus_info(void)
134 link = (reg >> 4) & 0x03; 139 link = (reg >> 4) & 0x03;
135 end = (reg & 0xfff000) | 0xfff; 140 end = (reg & 0xfff000) | 0xfff;
136 141
137 /* find the position */ 142 info = find_pci_root_info(node, link);
138 for (j = 0; j < pci_root_num; j++) { 143 if (!info)
139 info = &pci_root_info[j];
140 if (info->node == node && info->link == link)
141 break;
142 }
143 if (j == pci_root_num)
144 continue; /* not found */ 144 continue; /* not found */
145 145
146 info = &pci_root_info[j];
147 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n", 146 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
148 node, link, start, end); 147 node, link, start, end);
149 148
@@ -155,13 +154,8 @@ static int __init early_fill_mp_bus_info(void)
155 } 154 }
156 /* add left over io port range to def node/link, [0, 0xffff] */ 155 /* add left over io port range to def node/link, [0, 0xffff] */
157 /* find the position */ 156 /* find the position */
158 for (j = 0; j < pci_root_num; j++) { 157 info = find_pci_root_info(def_node, def_link);
159 info = &pci_root_info[j]; 158 if (info) {
160 if (info->node == def_node && info->link == def_link)
161 break;
162 }
163 if (j < pci_root_num) {
164 info = &pci_root_info[j];
165 for (i = 0; i < RANGE_NUM; i++) { 159 for (i = 0; i < RANGE_NUM; i++) {
166 if (!range[i].end) 160 if (!range[i].end)
167 continue; 161 continue;
@@ -214,16 +208,10 @@ static int __init early_fill_mp_bus_info(void)
214 end <<= 8; 208 end <<= 8;
215 end |= 0xffff; 209 end |= 0xffff;
216 210
217 /* find the position */ 211 info = find_pci_root_info(node, link);
218 for (j = 0; j < pci_root_num; j++) {
219 info = &pci_root_info[j];
220 if (info->node == node && info->link == link)
221 break;
222 }
223 if (j == pci_root_num)
224 continue; /* not found */
225 212
226 info = &pci_root_info[j]; 213 if (!info)
214 continue;
227 215
228 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]", 216 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
229 node, link, start, end); 217 node, link, start, end);
@@ -291,14 +279,8 @@ static int __init early_fill_mp_bus_info(void)
291 * add left over mmio range to def node/link ? 279 * add left over mmio range to def node/link ?
292 * that is tricky, just record range in from start_min to 4G 280 * that is tricky, just record range in from start_min to 4G
293 */ 281 */
294 for (j = 0; j < pci_root_num; j++) { 282 info = find_pci_root_info(def_node, def_link);
295 info = &pci_root_info[j]; 283 if (info) {
296 if (info->node == def_node && info->link == def_link)
297 break;
298 }
299 if (j < pci_root_num) {
300 info = &pci_root_info[j];
301
302 for (i = 0; i < RANGE_NUM; i++) { 284 for (i = 0; i < RANGE_NUM; i++) {
303 if (!range[i].end) 285 if (!range[i].end)
304 continue; 286 continue;
@@ -309,20 +291,16 @@ static int __init early_fill_mp_bus_info(void)
309 } 291 }
310 } 292 }
311 293
312 for (i = 0; i < pci_root_num; i++) { 294 list_for_each_entry(info, &pci_root_infos, list) {
313 int res_num;
314 int busnum; 295 int busnum;
296 struct pci_root_res *root_res;
315 297
316 info = &pci_root_info[i];
317 res_num = info->res_num;
318 busnum = info->bus_min; 298 busnum = info->bus_min;
319 printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", 299 printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
320 info->bus_min, info->bus_max, info->node, info->link); 300 info->bus_min, info->bus_max, info->node, info->link);
321 for (j = 0; j < res_num; j++) { 301 list_for_each_entry(root_res, &info->resources, list)
322 res = &info->res[j]; 302 printk(KERN_DEBUG "bus: %02x %pR\n",
323 printk(KERN_DEBUG "bus: %02x index %x %pR\n", 303 busnum, &root_res->res);
324 busnum, j, res);
325 }
326 } 304 }
327 305
328 return 0; 306 return 0;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index f3a7c569a403..614392ced7d6 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -22,19 +22,15 @@
22static void __init cnb20le_res(u8 bus, u8 slot, u8 func) 22static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
23{ 23{
24 struct pci_root_info *info; 24 struct pci_root_info *info;
25 struct pci_root_res *root_res;
25 struct resource res; 26 struct resource res;
26 u16 word1, word2; 27 u16 word1, word2;
27 u8 fbus, lbus; 28 u8 fbus, lbus;
28 int i;
29
30 info = &pci_root_info[pci_root_num];
31 pci_root_num++;
32 29
33 /* read the PCI bus numbers */ 30 /* read the PCI bus numbers */
34 fbus = read_pci_config_byte(bus, slot, func, 0x44); 31 fbus = read_pci_config_byte(bus, slot, func, 0x44);
35 lbus = read_pci_config_byte(bus, slot, func, 0x45); 32 lbus = read_pci_config_byte(bus, slot, func, 0x45);
36 info->bus_min = fbus; 33 info = alloc_pci_root_info(fbus, lbus, 0, 0);
37 info->bus_max = lbus;
38 34
39 /* 35 /*
40 * Add the legacy IDE ports on bus 0 36 * Add the legacy IDE ports on bus 0
@@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
86 res.flags = IORESOURCE_BUS; 82 res.flags = IORESOURCE_BUS;
87 printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res); 83 printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
88 84
89 for (i = 0; i < info->res_num; i++) 85 list_for_each_entry(root_res, &info->resources, list)
90 printk(KERN_INFO "host bridge window %pR\n", &info->res[i]); 86 printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
91} 87}
92 88
93static int __init broadcom_postcore_init(void) 89static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index fd3f65510e9d..306579f7d0fd 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -4,35 +4,38 @@
4 4
5#include "bus_numa.h" 5#include "bus_numa.h"
6 6
7int pci_root_num; 7LIST_HEAD(pci_root_infos);
8struct pci_root_info pci_root_info[PCI_ROOT_NR];
9 8
10void x86_pci_root_bus_resources(int bus, struct list_head *resources) 9static struct pci_root_info *x86_find_pci_root_info(int bus)
11{ 10{
12 int i;
13 int j;
14 struct pci_root_info *info; 11 struct pci_root_info *info;
15 12
16 if (!pci_root_num) 13 if (list_empty(&pci_root_infos))
17 goto default_resources; 14 return NULL;
18 15
19 for (i = 0; i < pci_root_num; i++) { 16 list_for_each_entry(info, &pci_root_infos, list)
20 if (pci_root_info[i].bus_min == bus) 17 if (info->bus_min == bus)
21 break; 18 return info;
22 } 19
20 return NULL;
21}
23 22
24 if (i == pci_root_num) 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
28 if (!info)
25 goto default_resources; 29 goto default_resources;
26 30
27 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", 31 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
28 bus); 32 bus);
29 33
30 info = &pci_root_info[i]; 34 list_for_each_entry(root_res, &info->resources, list) {
31 for (j = 0; j < info->res_num; j++) {
32 struct resource *res; 35 struct resource *res;
33 struct resource *root; 36 struct resource *root;
34 37
35 res = &info->res[j]; 38 res = &root_res->res;
36 pci_add_resource(resources, res); 39 pci_add_resource(resources, res);
37 if (res->flags & IORESOURCE_IO) 40 if (res->flags & IORESOURCE_IO)
38 root = &ioport_resource; 41 root = &ioport_resource;
@@ -53,11 +56,32 @@ default_resources:
53 pci_add_resource(resources, &iomem_resource); 56 pci_add_resource(resources, &iomem_resource);
54} 57}
55 58
59struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
60 int node, int link)
61{
62 struct pci_root_info *info;
63
64 info = kzalloc(sizeof(*info), GFP_KERNEL);
65
66 if (!info)
67 return info;
68
69 INIT_LIST_HEAD(&info->resources);
70 info->bus_min = bus_min;
71 info->bus_max = bus_max;
72 info->node = node;
73 info->link = link;
74
75 list_add_tail(&info->list, &pci_root_infos);
76
77 return info;
78}
79
56void __devinit update_res(struct pci_root_info *info, resource_size_t start, 80void __devinit update_res(struct pci_root_info *info, resource_size_t start,
57 resource_size_t end, unsigned long flags, int merge) 81 resource_size_t end, unsigned long flags, int merge)
58{ 82{
59 int i;
60 struct resource *res; 83 struct resource *res;
84 struct pci_root_res *root_res;
61 85
62 if (start > end) 86 if (start > end)
63 return; 87 return;
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
69 goto addit; 93 goto addit;
70 94
71 /* try to merge it with old one */ 95 /* try to merge it with old one */
72 for (i = 0; i < info->res_num; i++) { 96 list_for_each_entry(root_res, &info->resources, list) {
73 resource_size_t final_start, final_end; 97 resource_size_t final_start, final_end;
74 resource_size_t common_start, common_end; 98 resource_size_t common_start, common_end;
75 99
76 res = &info->res[i]; 100 res = &root_res->res;
77 if (res->flags != flags) 101 if (res->flags != flags)
78 continue; 102 continue;
79 103
@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
93addit: 117addit:
94 118
95 /* need to add that */ 119 /* need to add that */
96 if (info->res_num >= RES_NUM) 120 root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
121 if (!root_res)
97 return; 122 return;
98 123
99 res = &info->res[info->res_num]; 124 res = &root_res->res;
100 res->name = info->name; 125 res->name = info->name;
101 res->flags = flags; 126 res->flags = flags;
102 res->start = start; 127 res->start = start;
103 res->end = end; 128 res->end = end;
104 res->child = NULL; 129
105 info->res_num++; 130 list_add_tail(&root_res->list, &info->resources);
106} 131}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 804a4b40c31a..226a466b2b2b 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -4,22 +4,24 @@
4 * sub bus (transparent) will use entres from 3 to store extra from 4 * sub bus (transparent) will use entres from 3 to store extra from
5 * root, so need to make sure we have enough slot there. 5 * root, so need to make sure we have enough slot there.
6 */ 6 */
7#define RES_NUM 16 7struct pci_root_res {
8 struct list_head list;
9 struct resource res;
10};
11
8struct pci_root_info { 12struct pci_root_info {
13 struct list_head list;
9 char name[12]; 14 char name[12];
10 unsigned int res_num; 15 struct list_head resources;
11 struct resource res[RES_NUM];
12 int bus_min; 16 int bus_min;
13 int bus_max; 17 int bus_max;
14 int node; 18 int node;
15 int link; 19 int link;
16}; 20};
17 21
18/* 4 at this time, it may become to 32 */ 22extern struct list_head pci_root_infos;
19#define PCI_ROOT_NR 4 23struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
20extern int pci_root_num; 24 int node, int link);
21extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
22
23extern void update_res(struct pci_root_info *info, resource_size_t start, 25extern void update_res(struct pci_root_info *info, resource_size_t start,
24 resource_size_t end, unsigned long flags, int merge); 26 resource_size_t end, unsigned long flags, int merge);
25#endif 27#endif