bus_numa.c 3.3 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
	list_for_each_entry(info, &pci_root_infos, list)
14
		if (info->busn.start == bus)
15 16 17 18
			return info;

	return NULL;
}
19

20 21 22 23 24 25 26 27 28 29
int x86_pci_root_bus_node(int bus)
{
	struct pci_root_info *info = x86_find_pci_root_info(bus);

	if (!info)
		return NUMA_NO_NODE;

	return info->node;
}

30 31 32 33
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;
34
	struct resource_entry *window;
35
	bool found = false;
36 37

	if (!info)
38
		goto default_resources;
39

40 41
	printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
	       bus);
42

43
	/* already added by acpi ? */
44
	resource_list_for_each_entry(window, resources)
45 46 47 48 49 50 51 52
		if (window->res->flags & IORESOURCE_BUS) {
			found = true;
			break;
		}

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

53
	list_for_each_entry(root_res, &info->resources, list) {
54 55 56
		struct resource *res;
		struct resource *root;

57
		res = &root_res->res;
58
		pci_add_resource(resources, res);
59 60 61 62 63 64
		if (res->flags & IORESOURCE_IO)
			root = &ioport_resource;
		else
			root = &iomem_resource;
		insert_resource(root, res);
	}
65 66 67 68 69 70 71 72 73 74 75
	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);
76 77
}

78 79 80 81 82 83 84 85 86 87
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;

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

90
	INIT_LIST_HEAD(&info->resources);
91 92 93 94
	info->busn.name  = info->name;
	info->busn.start = bus_min;
	info->busn.end   = bus_max;
	info->busn.flags = IORESOURCE_BUS;
95 96 97 98 99 100 101 102
	info->node = node;
	info->link = link;

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

	return info;
}

103 104
void update_res(struct pci_root_info *info, resource_size_t start,
		resource_size_t end, unsigned long flags, int merge)
105 106
{
	struct resource *res;
107
	struct pci_root_res *root_res;
108 109 110 111

	if (start > end)
		return;

Y
Yinghai Lu 已提交
112 113 114
	if (start == MAX_RESOURCE)
		return;

115 116 117 118
	if (!merge)
		goto addit;

	/* try to merge it with old one */
119
	list_for_each_entry(root_res, &info->resources, list) {
120 121
		resource_size_t final_start, final_end;
		resource_size_t common_start, common_end;
122

123
		res = &root_res->res;
124 125 126
		if (res->flags != flags)
			continue;

127 128
		common_start = max(res->start, start);
		common_end = min(res->end, end);
129 130 131
		if (common_start > common_end + 1)
			continue;

132 133
		final_start = min(res->start, start);
		final_end = max(res->end, end);
134 135 136 137 138 139 140 141 142

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

addit:

	/* need to add that */
143 144
	root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
	if (!root_res)
145 146
		return;

147
	res = &root_res->res;
148 149 150 151
	res->name = info->name;
	res->flags = flags;
	res->start = start;
	res->end = end;
152 153

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