bus_numa.c 3.2 KB
Newer Older
1 2
#include <linux/init.h>
#include <linux/pci.h>
Y
Yinghai Lu 已提交
3
#include <linux/range.h>
4 5 6

#include "bus_numa.h"

7
LIST_HEAD(pci_root_infos);
8

9
static struct pci_root_info *x86_find_pci_root_info(int bus)
10 11 12
{
	struct pci_root_info *info;

13 14
	if (list_empty(&pci_root_infos))
		return NULL;
15

16
	list_for_each_entry(info, &pci_root_infos, list)
17
		if (info->busn.start == bus)
18 19 20 21
			return info;

	return NULL;
}
22

23 24 25 26
void x86_pci_root_bus_resources(int bus, struct list_head *resources)
{
	struct pci_root_info *info = x86_find_pci_root_info(bus);
	struct pci_root_res *root_res;
27 28
	struct pci_host_bridge_window *window;
	bool found = false;
29 30

	if (!info)
31
		goto default_resources;
32

33 34
	printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
	       bus);
35

36 37 38 39 40 41 42 43 44 45
	/* already added by acpi ? */
	list_for_each_entry(window, resources, list)
		if (window->res->flags & IORESOURCE_BUS) {
			found = true;
			break;
		}

	if (!found)
		pci_add_resource(resources, &info->busn);

46
	list_for_each_entry(root_res, &info->resources, list) {
47 48 49
		struct resource *res;
		struct resource *root;

50
		res = &root_res->res;
51
		pci_add_resource(resources, res);
52 53 54 55 56 57
		if (res->flags & IORESOURCE_IO)
			root = &ioport_resource;
		else
			root = &iomem_resource;
		insert_resource(root, res);
	}
58 59 60 61 62 63 64 65 66 67 68
	return;

default_resources:
	/*
	 * We don't have any host bridge aperture information from the
	 * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
	 * so fall back to the defaults historically used by pci_create_bus().
	 */
	printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
	pci_add_resource(resources, &ioport_resource);
	pci_add_resource(resources, &iomem_resource);
69 70
}

71 72 73 74 75 76 77 78 79 80
struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
						 int node, int link)
{
	struct pci_root_info *info;

	info = kzalloc(sizeof(*info), GFP_KERNEL);

	if (!info)
		return info;

81 82
	sprintf(info->name, "PCI Bus #%02x", bus_min);

83
	INIT_LIST_HEAD(&info->resources);
84 85 86 87
	info->busn.name  = info->name;
	info->busn.start = bus_min;
	info->busn.end   = bus_max;
	info->busn.flags = IORESOURCE_BUS;
88 89 90 91 92 93 94 95
	info->node = node;
	info->link = link;

	list_add_tail(&info->list, &pci_root_infos);

	return info;
}

96 97
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
			  resource_size_t end, unsigned long flags, int merge)
98 99
{
	struct resource *res;
100
	struct pci_root_res *root_res;
101 102 103 104

	if (start > end)
		return;

Y
Yinghai Lu 已提交
105 106 107
	if (start == MAX_RESOURCE)
		return;

108 109 110 111
	if (!merge)
		goto addit;

	/* try to merge it with old one */
112
	list_for_each_entry(root_res, &info->resources, list) {
113 114
		resource_size_t final_start, final_end;
		resource_size_t common_start, common_end;
115

116
		res = &root_res->res;
117 118 119
		if (res->flags != flags)
			continue;

120 121
		common_start = max(res->start, start);
		common_end = min(res->end, end);
122 123 124
		if (common_start > common_end + 1)
			continue;

125 126
		final_start = min(res->start, start);
		final_end = max(res->end, end);
127 128 129 130 131 132 133 134 135

		res->start = final_start;
		res->end = final_end;
		return;
	}

addit:

	/* need to add that */
136 137
	root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
	if (!root_res)
138 139
		return;

140
	res = &root_res->res;
141 142 143 144
	res->name = info->name;
	res->flags = flags;
	res->start = start;
	res->end = end;
145 146

	list_add_tail(&root_res->list, &info->resources);
147
}