blob: 306579f7d0fdc4283a332911844fb97830c915dc [file] [log] [blame]
Yinghai Lu67f241f2009-11-11 22:27:40 -08001#include <linux/init.h>
2#include <linux/pci.h>
Yinghai Lu9ad3f2c2010-02-10 01:20:11 -08003#include <linux/range.h>
Yinghai Lu67f241f2009-11-11 22:27:40 -08004
5#include "bus_numa.h"
6
Yinghai Lud28e5ac2012-04-02 18:31:54 -07007LIST_HEAD(pci_root_infos);
8
9static 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->bus_min == bus)
18 return info;
19
20 return NULL;
21}
Yinghai Lu67f241f2009-11-11 22:27:40 -080022
Bjorn Helgaas2cd69752011-10-28 16:28:14 -060023void x86_pci_root_bus_resources(int bus, struct list_head *resources)
Yinghai Lu67f241f2009-11-11 22:27:40 -080024{
Yinghai Lud28e5ac2012-04-02 18:31:54 -070025 struct pci_root_info *info = x86_find_pci_root_info(bus);
26 struct pci_root_res *root_res;
Yinghai Lu67f241f2009-11-11 22:27:40 -080027
Yinghai Lud28e5ac2012-04-02 18:31:54 -070028 if (!info)
Bjorn Helgaas2cd69752011-10-28 16:28:14 -060029 goto default_resources;
Yinghai Lu67f241f2009-11-11 22:27:40 -080030
Bjorn Helgaas2cd69752011-10-28 16:28:14 -060031 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
32 bus);
Yinghai Lu67f241f2009-11-11 22:27:40 -080033
Yinghai Lud28e5ac2012-04-02 18:31:54 -070034 list_for_each_entry(root_res, &info->resources, list) {
Yinghai Lu67f241f2009-11-11 22:27:40 -080035 struct resource *res;
36 struct resource *root;
37
Yinghai Lud28e5ac2012-04-02 18:31:54 -070038 res = &root_res->res;
Bjorn Helgaas2cd69752011-10-28 16:28:14 -060039 pci_add_resource(resources, res);
Yinghai Lu67f241f2009-11-11 22:27:40 -080040 if (res->flags & IORESOURCE_IO)
41 root = &ioport_resource;
42 else
43 root = &iomem_resource;
44 insert_resource(root, res);
45 }
Bjorn Helgaas2cd69752011-10-28 16:28:14 -060046 return;
47
48default_resources:
49 /*
50 * We don't have any host bridge aperture information from the
51 * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
52 * so fall back to the defaults historically used by pci_create_bus().
53 */
54 printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
55 pci_add_resource(resources, &ioport_resource);
56 pci_add_resource(resources, &iomem_resource);
Yinghai Lu67f241f2009-11-11 22:27:40 -080057}
58
Yinghai Lud28e5ac2012-04-02 18:31:54 -070059struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
60 int node, int link)
61{
62 struct pci_root_info *info;
63
64 info = kzalloc(sizeof(*info), GFP_KERNEL);
65
66 if (!info)
67 return info;
68
69 INIT_LIST_HEAD(&info->resources);
70 info->bus_min = bus_min;
71 info->bus_max = bus_max;
72 info->node = node;
73 info->link = link;
74
75 list_add_tail(&info->list, &pci_root_infos);
76
77 return info;
78}
79
Yinghai Lub74fd232010-02-10 01:20:08 -080080void __devinit update_res(struct pci_root_info *info, resource_size_t start,
81 resource_size_t end, unsigned long flags, int merge)
Yinghai Lu67f241f2009-11-11 22:27:40 -080082{
Yinghai Lu67f241f2009-11-11 22:27:40 -080083 struct resource *res;
Yinghai Lud28e5ac2012-04-02 18:31:54 -070084 struct pci_root_res *root_res;
Yinghai Lu67f241f2009-11-11 22:27:40 -080085
86 if (start > end)
87 return;
88
Yinghai Lu9ad3f2c2010-02-10 01:20:11 -080089 if (start == MAX_RESOURCE)
90 return;
91
Yinghai Lu67f241f2009-11-11 22:27:40 -080092 if (!merge)
93 goto addit;
94
95 /* try to merge it with old one */
Yinghai Lud28e5ac2012-04-02 18:31:54 -070096 list_for_each_entry(root_res, &info->resources, list) {
Yinghai Lub74fd232010-02-10 01:20:08 -080097 resource_size_t final_start, final_end;
98 resource_size_t common_start, common_end;
Yinghai Lu67f241f2009-11-11 22:27:40 -080099
Yinghai Lud28e5ac2012-04-02 18:31:54 -0700100 res = &root_res->res;
Yinghai Lu67f241f2009-11-11 22:27:40 -0800101 if (res->flags != flags)
102 continue;
103
Yinghai Lub74fd232010-02-10 01:20:08 -0800104 common_start = max(res->start, start);
105 common_end = min(res->end, end);
Yinghai Lu67f241f2009-11-11 22:27:40 -0800106 if (common_start > common_end + 1)
107 continue;
108
Yinghai Lub74fd232010-02-10 01:20:08 -0800109 final_start = min(res->start, start);
110 final_end = max(res->end, end);
Yinghai Lu67f241f2009-11-11 22:27:40 -0800111
112 res->start = final_start;
113 res->end = final_end;
114 return;
115 }
116
117addit:
118
119 /* need to add that */
Yinghai Lud28e5ac2012-04-02 18:31:54 -0700120 root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
121 if (!root_res)
Yinghai Lu67f241f2009-11-11 22:27:40 -0800122 return;
123
Yinghai Lud28e5ac2012-04-02 18:31:54 -0700124 res = &root_res->res;
Yinghai Lu67f241f2009-11-11 22:27:40 -0800125 res->name = info->name;
126 res->flags = flags;
127 res->start = start;
128 res->end = end;
Yinghai Lud28e5ac2012-04-02 18:31:54 -0700129
130 list_add_tail(&root_res->list, &info->resources);
Yinghai Lu67f241f2009-11-11 22:27:40 -0800131}