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 pci_host_bridge_window *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 list_for_each_entry(window, resources, list) 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 struct resource *res; 55 struct resource *root; 56 57 res = &root_res->res; 58 pci_add_resource(resources, res); 59 if (res->flags & IORESOURCE_IO) 60 root = &ioport_resource; 61 else 62 root = &iomem_resource; 63 insert_resource(root, res); 64 } 65 return; 66 67 default_resources: 68 /* 69 * We don't have any host bridge aperture information from the 70 * "native host bridge drivers," e.g., amd_bus or broadcom_bus, 71 * so fall back to the defaults historically used by pci_create_bus(). 72 */ 73 printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus); 74 pci_add_resource(resources, &ioport_resource); 75 pci_add_resource(resources, &iomem_resource); 76 } 77 78 struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max, 79 int node, int link) 80 { 81 struct pci_root_info *info; 82 83 info = kzalloc(sizeof(*info), GFP_KERNEL); 84 85 if (!info) 86 return info; 87 88 sprintf(info->name, "PCI Bus #%02x", bus_min); 89 90 INIT_LIST_HEAD(&info->resources); 91 info->busn.name = info->name; 92 info->busn.start = bus_min; 93 info->busn.end = bus_max; 94 info->busn.flags = IORESOURCE_BUS; 95 info->node = node; 96 info->link = link; 97 98 list_add_tail(&info->list, &pci_root_infos); 99 100 return info; 101 } 102 103 void update_res(struct pci_root_info *info, resource_size_t start, 104 resource_size_t end, unsigned long flags, int merge) 105 { 106 struct resource *res; 107 struct pci_root_res *root_res; 108 109 if (start > end) 110 return; 111 112 if (start == MAX_RESOURCE) 113 return; 114 115 if (!merge) 116 goto addit; 117 118 /* try to merge it with old one */ 119 list_for_each_entry(root_res, &info->resources, list) { 120 resource_size_t final_start, final_end; 121 resource_size_t common_start, common_end; 122 123 res = &root_res->res; 124 if (res->flags != flags) 125 continue; 126 127 common_start = max(res->start, start); 128 common_end = min(res->end, end); 129 if (common_start > common_end + 1) 130 continue; 131 132 final_start = min(res->start, start); 133 final_end = max(res->end, end); 134 135 res->start = final_start; 136 res->end = final_end; 137 return; 138 } 139 140 addit: 141 142 /* need to add that */ 143 root_res = kzalloc(sizeof(*root_res), GFP_KERNEL); 144 if (!root_res) 145 return; 146 147 res = &root_res->res; 148 res->name = info->name; 149 res->flags = flags; 150 res->start = start; 151 res->end = end; 152 153 list_add_tail(&root_res->list, &info->resources); 154 } 155