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, &info->busn); 53 54 list_for_each_entry(root_res, &info->resources, list) 55 pci_add_resource(resources, &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, &ioport_resource); 67 pci_add_resource(resources, &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(sizeof(*info), GFP_KERNEL); 76 77 if (!info) 78 return info; 79 80 sprintf(info->name, "PCI Bus #%02x", bus_min); 81 82 INIT_LIST_HEAD(&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(&info->list, &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(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(&root_res->list, &info->resources); 146 } 147