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