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