acpi.c 12.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/init.h>
4
#include <linux/irq.h>
5
#include <linux/dmi.h>
6
#include <linux/slab.h>
7
#include <asm/numa.h>
8
#include <asm/pci_x86.h>
L
Linus Torvalds 已提交
9

10
struct pci_root_info {
11
	struct acpi_device *bridge;
12
	char name[16];
13
	struct pci_sysdata sd;
14 15 16 17 18 19
#ifdef	CONFIG_PCI_MMCONFIG
	bool mcfg_added;
	u16 segment;
	u8 start_bus;
	u8 end_bus;
#endif
20 21
};

22
static bool pci_use_crs = true;
B
Bjorn Helgaas 已提交
23
static bool pci_ignore_seg = false;
24 25 26 27 28 29 30

static int __init set_use_crs(const struct dmi_system_id *id)
{
	pci_use_crs = true;
	return 0;
}

31 32 33 34 35 36
static int __init set_nouse_crs(const struct dmi_system_id *id)
{
	pci_use_crs = false;
	return 0;
}

B
Bjorn Helgaas 已提交
37 38 39 40 41 42 43 44
static int __init set_ignore_seg(const struct dmi_system_id *id)
{
	printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
	pci_ignore_seg = true;
	return 0;
}

static const struct dmi_system_id pci_crs_quirks[] __initconst = {
45 46 47 48 49 50 51 52 53
	/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
	{
		.callback = set_use_crs,
		.ident = "IBM System x3800",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
			DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
		},
	},
54 55 56 57 58 59 60 61 62
	/* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */
	/* 2006 AMD HT/VIA system with two host bridges */
        {
		.callback = set_use_crs,
		.ident = "ASRock ALiveSATA2-GLAN",
		.matches = {
			DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"),
                },
        },
63 64 65 66 67 68 69 70 71 72 73
	/* https://bugzilla.kernel.org/show_bug.cgi?id=30552 */
	/* 2006 AMD HT/VIA system with two host bridges */
	{
		.callback = set_use_crs,
		.ident = "ASUS M2V-MX SE",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
			DMI_MATCH(DMI_BOARD_NAME, "M2V-MX SE"),
			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
		},
	},
74 75 76 77 78 79 80 81 82 83
	/* https://bugzilla.kernel.org/show_bug.cgi?id=42619 */
	{
		.callback = set_use_crs,
		.ident = "MSI MS-7253",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
			DMI_MATCH(DMI_BOARD_NAME, "MS-7253"),
			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
		},
	},
84 85 86 87 88 89 90 91 92 93 94
	/* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/931368 */
	/* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1033299 */
	{
		.callback = set_use_crs,
		.ident = "Foxconn K8M890-8237A",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Foxconn"),
			DMI_MATCH(DMI_BOARD_NAME, "K8M890-8237A"),
			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
		},
	},
95

96 97 98 99 100 101 102 103 104 105 106 107
	/* Now for the blacklist.. */

	/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
	{
		.callback = set_nouse_crs,
		.ident = "Dell Studio 1557",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"),
			DMI_MATCH(DMI_BIOS_VERSION, "A09"),
		},
	},
108 109 110 111 112 113 114 115 116 117
	/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
	{
		.callback = set_nouse_crs,
		.ident = "Thinkpad SL510",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
			DMI_MATCH(DMI_BOARD_NAME, "2847DFG"),
			DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
		},
	},
B
Bjorn Helgaas 已提交
118 119 120 121 122 123 124 125 126 127

	/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
	{
		.callback = set_ignore_seg,
		.ident = "HP xw9300",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
			DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
		},
	},
128 129 130 131 132 133 134
	{}
};

void __init pci_acpi_crs_quirks(void)
{
	int year;

135 136 137 138
	if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) {
		if (iomem_resource.end <= 0xffffffff)
			pci_use_crs = false;
	}
139

B
Bjorn Helgaas 已提交
140
	dmi_check_system(pci_crs_quirks);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

	/*
	 * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
	 * takes precedence over anything we figured out above.
	 */
	if (pci_probe & PCI_ROOT_NO_CRS)
		pci_use_crs = false;
	else if (pci_probe & PCI_USE__CRS)
		pci_use_crs = true;

	printk(KERN_INFO "PCI: %s host bridge windows from ACPI; "
	       "if necessary, use \"pci=%s\" and report a bug\n",
	       pci_use_crs ? "Using" : "Ignoring",
	       pci_use_crs ? "nocrs" : "use_crs");
}

157
#ifdef	CONFIG_PCI_MMCONFIG
158
static int check_segment(u16 seg, struct device *dev, char *estr)
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
{
	if (seg) {
		dev_err(dev,
			"%s can't access PCI configuration "
			"space under this host bridge.\n",
			estr);
		return -EIO;
	}

	/*
	 * Failure in adding MMCFG information is not fatal,
	 * just can't access extended configuration space of
	 * devices under this host bridge.
	 */
	dev_warn(dev,
		 "%s can't access extended PCI configuration "
		 "space under this bridge.\n",
		 estr);

	return 0;
}

181 182
static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
			  u8 end, phys_addr_t addr)
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
{
	int result;
	struct device *dev = &info->bridge->dev;

	info->start_bus = start;
	info->end_bus = end;
	info->mcfg_added = false;

	/* return success if MMCFG is not in use */
	if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
		return 0;

	if (!(pci_probe & PCI_PROBE_MMCONF))
		return check_segment(seg, dev, "MMCONFIG is disabled,");

	result = pci_mmconfig_insert(dev, seg, start, end, addr);
	if (result == 0) {
		/* enable MMCFG if it hasn't been enabled yet */
		if (raw_pci_ext_ops == NULL)
			raw_pci_ext_ops = &pci_mmcfg;
		info->mcfg_added = true;
	} else if (result != -EEXIST)
		return check_segment(seg, dev,
			 "fail to add MMCONFIG information,");

	return 0;
}

static void teardown_mcfg_map(struct pci_root_info *info)
{
	if (info->mcfg_added) {
		pci_mmconfig_delete(info->segment, info->start_bus,
				    info->end_bus);
		info->mcfg_added = false;
	}
}
#else
220
static int setup_mcfg_map(struct pci_root_info *info,
221 222 223 224 225 226 227 228 229 230
				    u16 seg, u8 start, u8 end,
				    phys_addr_t addr)
{
	return 0;
}
static void teardown_mcfg_map(struct pci_root_info *info)
{
}
#endif

231 232
static void validate_resources(struct device *dev, struct list_head *crs_res,
			       unsigned long type)
233
{
234 235 236
	LIST_HEAD(list);
	struct resource *res1, *res2, *root = NULL;
	struct resource_entry *tmp, *entry, *entry2;
237

238 239
	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
240

241 242 243 244
	list_splice_init(crs_res, &list);
	resource_list_for_each_entry_safe(entry, tmp, &list) {
		bool free = false;
		resource_size_t end;
245

246
		res1 = entry->res;
247
		if (!(res1->flags & type))
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
			goto next;

		/* Exclude non-addressable range or non-addressable portion */
		end = min(res1->end, root->end);
		if (end <= res1->start) {
			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
				 res1);
			free = true;
			goto next;
		} else if (res1->end != end) {
			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
				 res1, (unsigned long long)end + 1,
				 (unsigned long long)res1->end);
			res1->end = end;
		}
263

264 265
		resource_list_for_each_entry(entry2, crs_res) {
			res2 = entry2->res;
266 267 268 269 270 271 272 273
			if (!(res2->flags & type))
				continue;

			/*
			 * I don't like throwing away windows because then
			 * our resources no longer match the ACPI _CRS, but
			 * the kernel resource tree doesn't allow overlaps.
			 */
W
Wei Yang 已提交
274
			if (resource_overlaps(res1, res2)) {
275 276
				res2->start = min(res1->start, res2->start);
				res2->end = max(res1->end, res2->end);
277
				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
278
					 res2, res1);
279 280
				free = true;
				goto next;
281 282
			}
		}
283 284 285 286 287 288 289

next:
		resource_list_del(entry);
		if (free)
			resource_list_free_entry(entry);
		else
			resource_list_add_tail(entry, crs_res);
290 291 292
	}
}

293
static void add_resources(struct pci_root_info *info,
294 295
			  struct list_head *resources,
			  struct list_head *crs_res)
296
{
297 298
	struct resource_entry *entry, *tmp;
	struct resource *res, *conflict, *root = NULL;
299

300 301
	validate_resources(&info->bridge->dev, crs_res, IORESOURCE_MEM);
	validate_resources(&info->bridge->dev, crs_res, IORESOURCE_IO);
302

303 304
	resource_list_for_each_entry_safe(entry, tmp, crs_res) {
		res = entry->res;
305 306 307 308
		if (res->flags & IORESOURCE_MEM)
			root = &iomem_resource;
		else if (res->flags & IORESOURCE_IO)
			root = &ioport_resource;
309
		else
310
			BUG_ON(res);
311 312

		conflict = insert_resource_conflict(root, res);
313
		if (conflict) {
314 315 316
			dev_info(&info->bridge->dev,
				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
				 res, conflict->name, conflict);
317 318
			resource_list_destroy_entry(entry);
		}
319 320
	}

321
	list_splice_tail(crs_res, resources);
322 323
}

324
static void release_pci_root_info(struct pci_host_bridge *bridge)
325 326
{
	struct resource *res;
327 328
	struct resource_entry *entry;
	struct pci_root_info *info = bridge->release_data;
329

330 331 332 333 334
	resource_list_for_each_entry(entry, &bridge->windows) {
		res = entry->res;
		if (res->parent &&
		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
			release_resource(res);
335 336
	}

337
	teardown_mcfg_map(info);
338 339
	kfree(info);
}
340

341 342
static void probe_pci_root_info(struct pci_root_info *info,
				struct acpi_device *device,
343 344
				int busnum, int domain,
				struct list_head *list)
345
{
346
	int ret;
347
	struct resource_entry *entry, *tmp;
348

349
	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
350
	info->bridge = device;
351 352 353 354 355 356 357 358 359 360
	ret = acpi_dev_get_resources(device, list,
				     acpi_dev_filter_resource_type_cb,
				     (void *)(IORESOURCE_IO | IORESOURCE_MEM));
	if (ret < 0)
		dev_warn(&device->dev,
			 "failed to parse _CRS method, error code %d\n", ret);
	else if (ret == 0)
		dev_dbg(&device->dev,
			"no IO and memory resources present in _CRS\n");
	else
361 362 363 364 365 366 367
		resource_list_for_each_entry_safe(entry, tmp, list) {
			if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
			    (entry->res->flags & IORESOURCE_DISABLED))
				resource_list_destroy_entry(entry);
			else
				entry->res->name = info->name;
		}
368 369
}

370
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
L
Linus Torvalds 已提交
371
{
372
	struct acpi_device *device = root->device;
373
	struct pci_root_info *info;
374 375
	int domain = root->segment;
	int busnum = root->secondary.start;
376 377
	struct resource_entry *res_entry;
	LIST_HEAD(crs_res);
378
	LIST_HEAD(resources);
379
	struct pci_bus *bus;
380
	struct pci_sysdata *sd;
Y
Yinghai Lu 已提交
381
	int node;
382

B
Bjorn Helgaas 已提交
383 384 385
	if (pci_ignore_seg)
		domain = 0;

386
	if (domain && !pci_domains_supported) {
387 388 389
		printk(KERN_WARNING "pci_bus %04x:%02x: "
		       "ignored (multiple domains not supported)\n",
		       domain, busnum);
390 391 392
		return NULL;
	}

393
	node = acpi_get_node(device->handle);
394
	if (node == NUMA_NO_NODE) {
395
		node = x86_pci_root_bus_node(busnum);
396 397 398 399
		if (node != 0 && node != NUMA_NO_NODE)
			dev_info(&device->dev, FW_BUG "no _PXM; falling back to node %d from hardware (may be inconsistent with ACPI node numbers)\n",
				node);
	}
400

401 402
	if (node != NUMA_NO_NODE && !node_online(node))
		node = NUMA_NO_NODE;
Y
Yinghai Lu 已提交
403

404
	info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
405
	if (!info) {
406 407
		printk(KERN_WARNING "pci_bus %04x:%02x: "
		       "ignored (out of memory)\n", domain, busnum);
408 409
		return NULL;
	}
410

411
	sd = &info->sd;
412
	sd->domain = domain;
Y
Yinghai Lu 已提交
413
	sd->node = node;
414
	sd->companion = device;
B
Bjorn Helgaas 已提交
415

416 417 418
	bus = pci_find_bus(domain, busnum);
	if (bus) {
		/*
B
Bjorn Helgaas 已提交
419 420
		 * If the desired bus has been scanned already, replace
		 * its bus->sysdata.
421 422
		 */
		memcpy(bus->sysdata, sd, sizeof(*sd));
423
		kfree(info);
424
	} else {
425 426
		/* insert busn res at first */
		pci_add_resource(&resources,  &root->secondary);
427

428 429 430 431
		/*
		 * _CRS with no apertures is normal, so only fall back to
		 * defaults or native bridge info if we're ignoring _CRS.
		 */
432 433 434 435 436 437 438 439 440
		probe_pci_root_info(info, device, busnum, domain, &crs_res);
		if (pci_use_crs) {
			add_resources(info, &resources, &crs_res);
		} else {
			resource_list_for_each_entry(res_entry, &crs_res)
				dev_printk(KERN_DEBUG, &device->dev,
					   "host bridge window %pR (ignored)\n",
					   res_entry->res);
			resource_list_free(&crs_res);
441
			x86_pci_root_bus_resources(busnum, &resources);
442
		}
443

444 445 446 447 448
		if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
				    (u8)root->secondary.end, root->mcfg_addr))
			bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
						  sd, &resources);

449
		if (bus) {
450
			pci_scan_child_bus(bus);
451 452 453 454
			pci_set_host_bridge_release(
				to_pci_host_bridge(bus->bridge),
				release_pci_root_info, info);
		} else {
455 456 457
			resource_list_free(&resources);
			teardown_mcfg_map(info);
			kfree(info);
458
		}
459
	}
460

461 462 463 464 465
	/* After the PCI-E bus has been walked and all devices discovered,
	 * configure any settings of the fabric that might be necessary.
	 */
	if (bus) {
		struct pci_bus *child;
466 467
		list_for_each_entry(child, &bus->children, node)
			pcie_bus_configure_settings(child);
468 469
	}

470
	if (bus && node != NUMA_NO_NODE)
471
		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
472

473
	return bus;
L
Linus Torvalds 已提交
474 475
}

476 477 478 479
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
	struct pci_sysdata *sd = bridge->bus->sysdata;

480
	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
481 482 483
	return 0;
}

484
int __init pci_acpi_init(void)
L
Linus Torvalds 已提交
485 486 487 488
{
	struct pci_dev *dev = NULL;

	if (acpi_noirq)
489
		return -ENODEV;
L
Linus Torvalds 已提交
490 491 492 493

	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
	acpi_irq_penalty_init();
	pcibios_enable_irq = acpi_pci_irq_enable;
494
	pcibios_disable_irq = acpi_pci_irq_disable;
495
	x86_init.pci.init_irq = x86_init_noop;
L
Linus Torvalds 已提交
496 497 498 499 500 501 502 503

	if (pci_routeirq) {
		/*
		 * PCI IRQ routing is set up by pci_enable_device(), but we
		 * also do it here in case there are still broken drivers that
		 * don't use pci_enable_device().
		 */
		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
504
		for_each_pci_dev(dev)
L
Linus Torvalds 已提交
505
			acpi_pci_irq_enable(dev);
506
	}
L
Linus Torvalds 已提交
507 508 509

	return 0;
}