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 YL |
13 | if (list_empty(&pci_root_infos)) |
14 | return NULL; | |
67f241f4 | 15 | |
d28e5ac2 YL |
16 | list_for_each_entry(info, &pci_root_infos, list) |
17 | if (info->bus_min == bus) | |
18 | return info; | |
19 | ||
20 | return NULL; | |
21 | } | |
67f241f4 | 22 | |
d28e5ac2 YL |
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) | |
2cd6975a | 29 | goto default_resources; |
67f241f4 | 30 | |
2cd6975a BH |
31 | printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", |
32 | bus); | |
67f241f4 | 33 | |
d28e5ac2 | 34 | list_for_each_entry(root_res, &info->resources, list) { |
67f241f4 YL |
35 | struct resource *res; |
36 | struct resource *root; | |
37 | ||
d28e5ac2 | 38 | res = &root_res->res; |
2cd6975a | 39 | pci_add_resource(resources, res); |
67f241f4 YL |
40 | if (res->flags & IORESOURCE_IO) |
41 | root = &ioport_resource; | |
42 | else | |
43 | root = &iomem_resource; | |
44 | insert_resource(root, res); | |
45 | } | |
2cd6975a BH |
46 | return; |
47 | ||
48 | default_resources: | |
49 | /* | |
50 | * We don't have any host bridge aperture information from the | |
51 | * "native host bridge drivers," e.g., amd_bus or broadcom_bus, | |
52 | * so fall back to the defaults historically used by pci_create_bus(). | |
53 | */ | |
54 | printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus); | |
55 | pci_add_resource(resources, &ioport_resource); | |
56 | pci_add_resource(resources, &iomem_resource); | |
67f241f4 YL |
57 | } |
58 | ||
d28e5ac2 YL |
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 | ||
b74fd238 YL |
80 | void __devinit update_res(struct pci_root_info *info, resource_size_t start, |
81 | resource_size_t end, unsigned long flags, int merge) | |
67f241f4 | 82 | { |
67f241f4 | 83 | struct resource *res; |
d28e5ac2 | 84 | struct pci_root_res *root_res; |
67f241f4 YL |
85 | |
86 | if (start > end) | |
87 | return; | |
88 | ||
9ad3f2c7 YL |
89 | if (start == MAX_RESOURCE) |
90 | return; | |
91 | ||
67f241f4 YL |
92 | if (!merge) |
93 | goto addit; | |
94 | ||
95 | /* try to merge it with old one */ | |
d28e5ac2 | 96 | list_for_each_entry(root_res, &info->resources, list) { |
b74fd238 YL |
97 | resource_size_t final_start, final_end; |
98 | resource_size_t common_start, common_end; | |
67f241f4 | 99 | |
d28e5ac2 | 100 | res = &root_res->res; |
67f241f4 YL |
101 | if (res->flags != flags) |
102 | continue; | |
103 | ||
b74fd238 YL |
104 | common_start = max(res->start, start); |
105 | common_end = min(res->end, end); | |
67f241f4 YL |
106 | if (common_start > common_end + 1) |
107 | continue; | |
108 | ||
b74fd238 YL |
109 | final_start = min(res->start, start); |
110 | final_end = max(res->end, end); | |
67f241f4 YL |
111 | |
112 | res->start = final_start; | |
113 | res->end = final_end; | |
114 | return; | |
115 | } | |
116 | ||
117 | addit: | |
118 | ||
119 | /* need to add that */ | |
d28e5ac2 YL |
120 | root_res = kzalloc(sizeof(*root_res), GFP_KERNEL); |
121 | if (!root_res) | |
67f241f4 YL |
122 | return; |
123 | ||
d28e5ac2 | 124 | res = &root_res->res; |
67f241f4 YL |
125 | res->name = info->name; |
126 | res->flags = flags; | |
127 | res->start = start; | |
128 | res->end = end; | |
d28e5ac2 YL |
129 | |
130 | list_add_tail(&root_res->list, &info->resources); | |
67f241f4 | 131 | } |