1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
267f241f4SYinghai Lu #include <linux/init.h>
367f241f4SYinghai Lu #include <linux/pci.h>
49ad3f2c7SYinghai Lu #include <linux/range.h>
567f241f4SYinghai Lu
667f241f4SYinghai Lu #include "bus_numa.h"
767f241f4SYinghai Lu
8d28e5ac2SYinghai Lu LIST_HEAD(pci_root_infos);
9d28e5ac2SYinghai Lu
x86_find_pci_root_info(int bus)10d28e5ac2SYinghai Lu static struct pci_root_info *x86_find_pci_root_info(int bus)
11d28e5ac2SYinghai Lu {
12d28e5ac2SYinghai Lu struct pci_root_info *info;
13d28e5ac2SYinghai Lu
14d28e5ac2SYinghai Lu list_for_each_entry(info, &pci_root_infos, list)
15a10bb128SYinghai Lu if (info->busn.start == bus)
16d28e5ac2SYinghai Lu return info;
17d28e5ac2SYinghai Lu
18d28e5ac2SYinghai Lu return NULL;
19d28e5ac2SYinghai Lu }
2067f241f4SYinghai Lu
x86_pci_root_bus_node(int bus)21afcf21c2SBjorn Helgaas int x86_pci_root_bus_node(int bus)
22afcf21c2SBjorn Helgaas {
23afcf21c2SBjorn Helgaas struct pci_root_info *info = x86_find_pci_root_info(bus);
24afcf21c2SBjorn Helgaas
25afcf21c2SBjorn Helgaas if (!info)
26afcf21c2SBjorn Helgaas return NUMA_NO_NODE;
27afcf21c2SBjorn Helgaas
28afcf21c2SBjorn Helgaas return info->node;
29afcf21c2SBjorn Helgaas }
30afcf21c2SBjorn Helgaas
x86_pci_root_bus_resources(int bus,struct list_head * resources)312cd6975aSBjorn Helgaas void x86_pci_root_bus_resources(int bus, struct list_head *resources)
3267f241f4SYinghai Lu {
33d28e5ac2SYinghai Lu struct pci_root_info *info = x86_find_pci_root_info(bus);
34d28e5ac2SYinghai Lu struct pci_root_res *root_res;
3514d76b68SJiang Liu struct resource_entry *window;
36a10bb128SYinghai Lu bool found = false;
3767f241f4SYinghai Lu
38d28e5ac2SYinghai Lu if (!info)
392cd6975aSBjorn Helgaas goto default_resources;
4067f241f4SYinghai Lu
412cd6975aSBjorn Helgaas printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
422cd6975aSBjorn Helgaas bus);
4367f241f4SYinghai Lu
44a10bb128SYinghai Lu /* already added by acpi ? */
4514d76b68SJiang Liu resource_list_for_each_entry(window, resources)
46a10bb128SYinghai Lu if (window->res->flags & IORESOURCE_BUS) {
47a10bb128SYinghai Lu found = true;
48a10bb128SYinghai Lu break;
49a10bb128SYinghai Lu }
50a10bb128SYinghai Lu
51a10bb128SYinghai Lu if (!found)
52a10bb128SYinghai Lu pci_add_resource(resources, &info->busn);
53a10bb128SYinghai Lu
54727ae8beSLiu Jiang list_for_each_entry(root_res, &info->resources, list)
55727ae8beSLiu Jiang pci_add_resource(resources, &root_res->res);
5667f241f4SYinghai Lu
572cd6975aSBjorn Helgaas return;
582cd6975aSBjorn Helgaas
592cd6975aSBjorn Helgaas default_resources:
602cd6975aSBjorn Helgaas /*
612cd6975aSBjorn Helgaas * We don't have any host bridge aperture information from the
622cd6975aSBjorn Helgaas * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
632cd6975aSBjorn Helgaas * so fall back to the defaults historically used by pci_create_bus().
642cd6975aSBjorn Helgaas */
652cd6975aSBjorn Helgaas printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
662cd6975aSBjorn Helgaas pci_add_resource(resources, &ioport_resource);
672cd6975aSBjorn Helgaas pci_add_resource(resources, &iomem_resource);
6867f241f4SYinghai Lu }
6967f241f4SYinghai Lu
alloc_pci_root_info(int bus_min,int bus_max,int node,int link)70d28e5ac2SYinghai Lu struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
71d28e5ac2SYinghai Lu int node, int link)
72d28e5ac2SYinghai Lu {
73d28e5ac2SYinghai Lu struct pci_root_info *info;
74d28e5ac2SYinghai Lu
75d28e5ac2SYinghai Lu info = kzalloc(sizeof(*info), GFP_KERNEL);
76d28e5ac2SYinghai Lu
77d28e5ac2SYinghai Lu if (!info)
78d28e5ac2SYinghai Lu return info;
79d28e5ac2SYinghai Lu
80a10bb128SYinghai Lu sprintf(info->name, "PCI Bus #%02x", bus_min);
81a10bb128SYinghai Lu
82d28e5ac2SYinghai Lu INIT_LIST_HEAD(&info->resources);
83a10bb128SYinghai Lu info->busn.name = info->name;
84a10bb128SYinghai Lu info->busn.start = bus_min;
85a10bb128SYinghai Lu info->busn.end = bus_max;
86a10bb128SYinghai Lu info->busn.flags = IORESOURCE_BUS;
87d28e5ac2SYinghai Lu info->node = node;
88d28e5ac2SYinghai Lu info->link = link;
89d28e5ac2SYinghai Lu
90d28e5ac2SYinghai Lu list_add_tail(&info->list, &pci_root_infos);
91d28e5ac2SYinghai Lu
92d28e5ac2SYinghai Lu return info;
93d28e5ac2SYinghai Lu }
94d28e5ac2SYinghai Lu
update_res(struct pci_root_info * info,resource_size_t start,resource_size_t end,unsigned long flags,int merge)95a18e3690SGreg Kroah-Hartman void update_res(struct pci_root_info *info, resource_size_t start,
96b74fd238SYinghai Lu resource_size_t end, unsigned long flags, int merge)
9767f241f4SYinghai Lu {
9867f241f4SYinghai Lu struct resource *res;
99d28e5ac2SYinghai Lu struct pci_root_res *root_res;
10067f241f4SYinghai Lu
10167f241f4SYinghai Lu if (start > end)
10267f241f4SYinghai Lu return;
10367f241f4SYinghai Lu
104*3c9d017cSAndy Shevchenko if (start == RESOURCE_SIZE_MAX)
1059ad3f2c7SYinghai Lu return;
1069ad3f2c7SYinghai Lu
10767f241f4SYinghai Lu if (!merge)
10867f241f4SYinghai Lu goto addit;
10967f241f4SYinghai Lu
11067f241f4SYinghai Lu /* try to merge it with old one */
111d28e5ac2SYinghai Lu list_for_each_entry(root_res, &info->resources, list) {
112b74fd238SYinghai Lu resource_size_t final_start, final_end;
113b74fd238SYinghai Lu resource_size_t common_start, common_end;
11467f241f4SYinghai Lu
115d28e5ac2SYinghai Lu res = &root_res->res;
11667f241f4SYinghai Lu if (res->flags != flags)
11767f241f4SYinghai Lu continue;
11867f241f4SYinghai Lu
119b74fd238SYinghai Lu common_start = max(res->start, start);
120b74fd238SYinghai Lu common_end = min(res->end, end);
12167f241f4SYinghai Lu if (common_start > common_end + 1)
12267f241f4SYinghai Lu continue;
12367f241f4SYinghai Lu
124b74fd238SYinghai Lu final_start = min(res->start, start);
125b74fd238SYinghai Lu final_end = max(res->end, end);
12667f241f4SYinghai Lu
12767f241f4SYinghai Lu res->start = final_start;
12867f241f4SYinghai Lu res->end = final_end;
12967f241f4SYinghai Lu return;
13067f241f4SYinghai Lu }
13167f241f4SYinghai Lu
13267f241f4SYinghai Lu addit:
13367f241f4SYinghai Lu
13467f241f4SYinghai Lu /* need to add that */
135d28e5ac2SYinghai Lu root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
136d28e5ac2SYinghai Lu if (!root_res)
13767f241f4SYinghai Lu return;
13867f241f4SYinghai Lu
139d28e5ac2SYinghai Lu res = &root_res->res;
14067f241f4SYinghai Lu res->name = info->name;
14167f241f4SYinghai Lu res->flags = flags;
14267f241f4SYinghai Lu res->start = start;
14367f241f4SYinghai Lu res->end = end;
144d28e5ac2SYinghai Lu
145d28e5ac2SYinghai Lu list_add_tail(&root_res->list, &info->resources);
14667f241f4SYinghai Lu }
147