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