diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-04-02 21:31:54 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-04-30 16:52:43 -0400 |
commit | d28e5ac2a07e27638cf5ac061721b7969e17fe78 (patch) | |
tree | 4ae91ae8d95f3ef23d8fa9be5f1d02b8cdc53715 /arch/x86/pci/bus_numa.c | |
parent | 35cb05e5bdac209cfdfafbe50d89ee7069cb6237 (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/bus_numa.c')
-rw-r--r-- | arch/x86/pci/bus_numa.c | 69 |
1 files changed, 47 insertions, 22 deletions
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 | ||
7 | int pci_root_num; | 7 | LIST_HEAD(pci_root_infos); |
8 | struct pci_root_info pci_root_info[PCI_ROOT_NR]; | ||
9 | 8 | ||
10 | void x86_pci_root_bus_resources(int bus, struct list_head *resources) | 9 | static 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) | 23 | void 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 | ||
59 | struct 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 | |||
56 | void __devinit update_res(struct pci_root_info *info, resource_size_t start, | 80 | void __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, | |||
93 | addit: | 117 | addit: |
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 | } |