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