1 #include <linux/init.h> 2 #include <linux/pci.h> 3 #include <linux/range.h> 4 5 #include "bus_numa.h" 6 7 int pci_root_num; 8 struct pci_root_info pci_root_info[PCI_ROOT_NR]; 9 10 void x86_pci_root_bus_res_quirks(struct pci_bus *b) 11 { 12 int i; 13 int j; 14 struct pci_root_info *info; 15 16 /* don't go for it if _CRS is used already */ 17 if (b->resource[0] != &ioport_resource || 18 b->resource[1] != &iomem_resource) 19 return; 20 21 if (!pci_root_num) 22 return; 23 24 for (i = 0; i < pci_root_num; i++) { 25 if (pci_root_info[i].bus_min == b->number) 26 break; 27 } 28 29 if (i == pci_root_num) 30 return; 31 32 printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", 33 b->number); 34 35 pci_bus_remove_resources(b); 36 info = &pci_root_info[i]; 37 for (j = 0; j < info->res_num; j++) { 38 struct resource *res; 39 struct resource *root; 40 41 res = &info->res[j]; 42 pci_bus_add_resource(b, res, 0); 43 if (res->flags & IORESOURCE_IO) 44 root = &ioport_resource; 45 else 46 root = &iomem_resource; 47 insert_resource(root, res); 48 } 49 } 50 51 void __devinit update_res(struct pci_root_info *info, resource_size_t start, 52 resource_size_t end, unsigned long flags, int merge) 53 { 54 int i; 55 struct resource *res; 56 57 if (start > end) 58 return; 59 60 if (start == MAX_RESOURCE) 61 return; 62 63 if (!merge) 64 goto addit; 65 66 /* try to merge it with old one */ 67 for (i = 0; i < info->res_num; i++) { 68 resource_size_t final_start, final_end; 69 resource_size_t common_start, common_end; 70 71 res = &info->res[i]; 72 if (res->flags != flags) 73 continue; 74 75 common_start = max(res->start, start); 76 common_end = min(res->end, end); 77 if (common_start > common_end + 1) 78 continue; 79 80 final_start = min(res->start, start); 81 final_end = max(res->end, end); 82 83 res->start = final_start; 84 res->end = final_end; 85 return; 86 } 87 88 addit: 89 90 /* need to add that */ 91 if (info->res_num >= RES_NUM) 92 return; 93 94 res = &info->res[info->res_num]; 95 res->name = info->name; 96 res->flags = flags; 97 res->start = start; 98 res->end = end; 99 res->child = NULL; 100 info->res_num++; 101 } 102