bus_numa.c (3177B)
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 8LIST_HEAD(pci_root_infos); 9 10static 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 21int 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 31void 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 59default_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 70struct 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 95void 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 == MAX_RESOURCE) 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 132addit: 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}