pci_irq.c 14.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 *  pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $)
 *
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or (at
 *  your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */


28
#include <linux/dmi.h>
L
Linus Torvalds 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>

#define _COMPONENT		ACPI_PCI_COMPONENT
42
ACPI_MODULE_NAME("pci_irq");
L
Linus Torvalds 已提交
43

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
struct acpi_prt_entry {
	struct list_head	node;
	struct acpi_pci_id	id;
	u8			pin;
	struct {
		acpi_handle		handle;
		u32			index;
	}			link;
	u32			irq;
};

struct acpi_prt_list {
	int			count;
	struct list_head	entries;
};

L
Len Brown 已提交
60
static struct acpi_prt_list acpi_prt;
L
Linus Torvalds 已提交
61 62
static DEFINE_SPINLOCK(acpi_prt_lock);

63 64
static inline char pin_name(int pin)
{
65
	return 'A' + pin - 1;
66 67
}

L
Linus Torvalds 已提交
68 69 70 71
/* --------------------------------------------------------------------------
                         PCI IRQ Routing Table (PRT) Support
   -------------------------------------------------------------------------- */

72 73
static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
							  int pin)
L
Linus Torvalds 已提交
74
{
L
Len Brown 已提交
75
	struct acpi_prt_entry *entry = NULL;
76 77 78
	int segment = pci_domain_nr(dev->bus);
	int bus = dev->bus->number;
	int device = PCI_SLOT(dev->devfn);
L
Linus Torvalds 已提交
79 80

	if (!acpi_prt.count)
81
		return NULL;
L
Linus Torvalds 已提交
82 83 84 85 86 87 88

	/*
	 * Parse through all PRT entries looking for a match on the specified
	 * PCI device's segment, bus, device, and pin (don't care about func).
	 *
	 */
	spin_lock(&acpi_prt_lock);
89
	list_for_each_entry(entry, &acpi_prt.entries, node) {
L
Len Brown 已提交
90 91 92 93
		if ((segment == entry->id.segment)
		    && (bus == entry->id.bus)
		    && (device == entry->id.device)
		    && (pin == entry->pin)) {
L
Linus Torvalds 已提交
94
			spin_unlock(&acpi_prt_lock);
95
			return entry;
L
Linus Torvalds 已提交
96 97 98 99
		}
	}

	spin_unlock(&acpi_prt_lock);
100
	return NULL;
L
Linus Torvalds 已提交
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
static struct dmi_system_id medion_md9580[] = {
	{
		.ident = "Medion MD9580-F laptop",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
			DMI_MATCH(DMI_PRODUCT_NAME, "A555"),
		},
	},
	{ }
};

/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */
static struct dmi_system_id dell_optiplex[] = {
	{
		.ident = "Dell Optiplex GX1",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"),
		},
	},
	{ }
};

/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */
static struct dmi_system_id hp_t5710[] = {
	{
		.ident = "HP t5710",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"),
			DMI_MATCH(DMI_BOARD_NAME, "098Ch"),
		},
	},
	{ }
};

struct prt_quirk {
	struct dmi_system_id	*system;
	unsigned int		segment;
	unsigned int		bus;
	unsigned int		device;
	unsigned char		pin;
	char			*source;	/* according to BIOS */
	char			*actual_source;
};

150 151
#define PCI_INTX_PIN(c)		(c - 'A' + 1)

152 153 154 155 156 157
/*
 * These systems have incorrect _PRT entries.  The BIOS claims the PCI
 * interrupt at the listed segment/bus/device/pin is connected to the first
 * link device, but it is actually connected to the second.
 */
static struct prt_quirk prt_quirks[] = {
158
	{ medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'),
159 160
		"\\_SB_.PCI0.ISA_.LNKA",
		"\\_SB_.PCI0.ISA_.LNKB"},
161
	{ dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'),
162 163
		"\\_SB_.LNKB",
		"\\_SB_.LNKA"},
164
	{ hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'),
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		"\\_SB_.PCI0.LNK1",
		"\\_SB_.PCI0.LNK3"},
};

static void
do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
{
	int i;
	struct prt_quirk *quirk;

	for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) {
		quirk = &prt_quirks[i];

		/* All current quirks involve link devices, not GSIs */
		if (!prt->source)
			continue;

		if (dmi_check_system(quirk->system) &&
		    entry->id.segment == quirk->segment &&
		    entry->id.bus == quirk->bus &&
		    entry->id.device == quirk->device &&
186
		    entry->pin == quirk->pin &&
187 188 189
		    !strcmp(prt->source, quirk->source) &&
		    strlen(prt->source) >= strlen(quirk->actual_source)) {
			printk(KERN_WARNING PREFIX "firmware reports "
190
				"%04x:%02x:%02x PCI INT %c connected to %s; "
191 192
				"changing to %s\n",
				entry->id.segment, entry->id.bus,
193
				entry->id.device, pin_name(entry->pin),
194 195 196 197 198 199
				prt->source, quirk->actual_source);
			strcpy(prt->source, quirk->actual_source);
		}
	}
}

L
Linus Torvalds 已提交
200
static int
L
Len Brown 已提交
201 202
acpi_pci_irq_add_entry(acpi_handle handle,
		       int segment, int bus, struct acpi_pci_routing_table *prt)
L
Linus Torvalds 已提交
203
{
L
Len Brown 已提交
204
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
205

206
	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
L
Linus Torvalds 已提交
207
	if (!entry)
208
		return -ENOMEM;
L
Linus Torvalds 已提交
209

210 211 212 213 214
	/*
	 * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses
	 * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
	 * it here.
	 */
L
Linus Torvalds 已提交
215 216 217
	entry->id.segment = segment;
	entry->id.bus = bus;
	entry->id.device = (prt->address >> 16) & 0xFFFF;
218
	entry->pin = prt->pin + 1;
L
Linus Torvalds 已提交
219

220 221
	do_prt_fixups(entry, prt);

L
Linus Torvalds 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	/*
	 * Type 1: Dynamic
	 * ---------------
	 * The 'source' field specifies the PCI interrupt link device used to
	 * configure the IRQ assigned to this slot|dev|pin.  The 'source_index'
	 * indicates which resource descriptor in the resource template (of
	 * the link device) this interrupt is allocated from.
	 * 
	 * NOTE: Don't query the Link Device for IRQ information at this time
	 *       because Link Device enumeration may not have occurred yet
	 *       (e.g. exists somewhere 'below' this _PRT entry in the ACPI
	 *       namespace).
	 */
	if (prt->source[0]) {
		acpi_get_handle(handle, prt->source, &entry->link.handle);
		entry->link.index = prt->source_index;
	}
	/*
	 * Type 2: Static
	 * --------------
	 * The 'source' field is NULL, and the 'source_index' field specifies
	 * the IRQ value, which is hardwired to specific interrupt inputs on
	 * the interrupt controller.
	 */
	else
		entry->link.index = prt->source_index;

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
250
			      "      %04x:%02x:%02x[%c] -> %s[%d]\n",
L
Len Brown 已提交
251
			      entry->id.segment, entry->id.bus,
252 253
			      entry->id.device, pin_name(entry->pin),
			      prt->source, entry->link.index));
L
Linus Torvalds 已提交
254 255 256 257 258 259

	spin_lock(&acpi_prt_lock);
	list_add_tail(&entry->node, &acpi_prt.entries);
	acpi_prt.count++;
	spin_unlock(&acpi_prt_lock);

260
	return 0;
L
Linus Torvalds 已提交
261 262 263
}

static void
L
Len Brown 已提交
264
acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry)
L
Linus Torvalds 已提交
265
{
L
Len Brown 已提交
266
	if (segment == entry->id.segment && bus == entry->id.bus) {
L
Linus Torvalds 已提交
267 268 269 270 271 272
		acpi_prt.count--;
		list_del(&entry->node);
		kfree(entry);
	}
}

L
Len Brown 已提交
273
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
L
Linus Torvalds 已提交
274
{
275 276 277
	acpi_status status;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_pci_routing_table *entry;
L
Len Brown 已提交
278
	static int first_time = 1;
L
Linus Torvalds 已提交
279 280 281 282 283 284 285

	if (first_time) {
		acpi_prt.count = 0;
		INIT_LIST_HEAD(&acpi_prt.entries);
		first_time = 0;
	}

286 287 288 289
	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
	if (ACPI_FAILURE(status))
		return -ENODEV;
L
Linus Torvalds 已提交
290 291

	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
292
	       (char *) buffer.pointer);
L
Linus Torvalds 已提交
293

294
	kfree(buffer.pointer);
L
Linus Torvalds 已提交
295

296
	buffer.length = ACPI_ALLOCATE_BUFFER;
L
Linus Torvalds 已提交
297 298 299 300
	buffer.pointer = NULL;

	status = acpi_get_irq_routing_table(handle, &buffer);
	if (ACPI_FAILURE(status)) {
301 302
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
				acpi_format_exception(status)));
L
Linus Torvalds 已提交
303
		kfree(buffer.pointer);
304
		return -ENODEV;
L
Linus Torvalds 已提交
305 306
	}

307
	entry = buffer.pointer;
L
Linus Torvalds 已提交
308 309 310
	while (entry && (entry->length > 0)) {
		acpi_pci_irq_add_entry(handle, segment, bus, entry);
		entry = (struct acpi_pci_routing_table *)
L
Len Brown 已提交
311
		    ((unsigned long)entry + entry->length);
L
Linus Torvalds 已提交
312 313
	}

314
	kfree(buffer.pointer);
315
	return 0;
L
Linus Torvalds 已提交
316 317
}

L
Len Brown 已提交
318
void acpi_pci_irq_del_prt(int segment, int bus)
L
Linus Torvalds 已提交
319
{
L
Len Brown 已提交
320 321
	struct list_head *node = NULL, *n = NULL;
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
322

L
Len Brown 已提交
323
	if (!acpi_prt.count) {
L
Linus Torvalds 已提交
324 325 326
		return;
	}

L
Len Brown 已提交
327
	printk(KERN_DEBUG
328 329
	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
	       segment, bus);
L
Linus Torvalds 已提交
330 331 332 333 334 335 336 337
	spin_lock(&acpi_prt_lock);
	list_for_each_safe(node, n, &acpi_prt.entries) {
		entry = list_entry(node, struct acpi_prt_entry, node);

		acpi_pci_irq_del_entry(segment, bus, entry);
	}
	spin_unlock(&acpi_prt_lock);
}
L
Len Brown 已提交
338

L
Linus Torvalds 已提交
339 340 341
/* --------------------------------------------------------------------------
                          PCI Interrupt Routing Support
   -------------------------------------------------------------------------- */
342 343
static int
acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
B
Bob Moore 已提交
344
		      int *triggering, int *polarity, char **link)
345
{
L
Len Brown 已提交
346
	int irq;
347 348 349 350


	if (entry->link.handle) {
		irq = acpi_pci_link_allocate_irq(entry->link.handle,
B
Bob Moore 已提交
351 352
						 entry->link.index, triggering,
						 polarity, link);
353
		if (irq < 0) {
354 355
			printk(KERN_WARNING PREFIX
				      "Invalid IRQ link routing entry\n");
356
			return -1;
357 358 359
		}
	} else {
		irq = entry->link.index;
B
Bob Moore 已提交
360 361
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
362 363
	}

364
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found GSI %d\n", irq));
365
	return irq;
366 367 368
}

static int
369
acpi_pci_free_irq(struct acpi_prt_entry *entry)
370
{
L
Len Brown 已提交
371
	int irq;
372 373 374 375 376 377

	if (entry->link.handle) {
		irq = acpi_pci_link_free_irq(entry->link.handle);
	} else {
		irq = entry->link.index;
	}
378
	return irq;
379
}
L
Len Brown 已提交
380

381 382
static struct acpi_prt_entry *
acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
L
Linus Torvalds 已提交
383
{
384
	struct acpi_prt_entry *entry;
L
Linus Torvalds 已提交
385

386
	entry = acpi_pci_irq_find_prt_entry(dev, pin);
387 388
	if (entry) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
B
Bjorn Helgaas 已提交
389
				  pci_name(dev), pin_name(pin)));
390
		return entry;
L
Linus Torvalds 已提交
391
	}
L
Len Brown 已提交
392

393
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n",
B
Bjorn Helgaas 已提交
394
			  pci_name(dev), pin_name(pin)));
395
	return NULL;
L
Linus Torvalds 已提交
396 397
}

398 399
static struct acpi_prt_entry *
acpi_pci_irq_derive(struct pci_dev *dev, int pin)
L
Linus Torvalds 已提交
400
{
401
	struct acpi_prt_entry *entry = NULL;
L
Len Brown 已提交
402
	struct pci_dev *bridge = dev;
403
	u8 bridge_pin = 0, orig_pin = pin;
L
Linus Torvalds 已提交
404 405 406 407 408 409


	/* 
	 * Attempt to derive an IRQ for this device from a parent bridge's
	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
	 */
410
	while (bridge->bus->self) {
411
		pin = (((pin - 1) + PCI_SLOT(bridge->devfn)) % 4) + 1;
L
Linus Torvalds 已提交
412 413 414 415
		bridge = bridge->bus->self;

		if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
			/* PC card has the same IRQ as its cardbridge */
416
			bridge_pin = bridge->pin;
L
Linus Torvalds 已提交
417
			if (!bridge_pin) {
L
Len Brown 已提交
418 419 420
				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
						  "No interrupt pin configured for device %s\n",
						  pci_name(bridge)));
421
				return NULL;
L
Linus Torvalds 已提交
422 423 424 425
			}
			pin = bridge_pin;
		}

426
		entry = acpi_pci_irq_lookup(bridge, pin);
427 428 429 430 431 432 433
		if (entry) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					 "Derived GSI for %s INT %c from %s\n",
					 pci_name(dev), pin_name(orig_pin),
					 pci_name(bridge)));
			return entry;
		}
L
Linus Torvalds 已提交
434 435
	}

436 437 438
	dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
		 pin_name(orig_pin));
	return NULL;
L
Linus Torvalds 已提交
439 440 441 442 443 444 445 446
}

/*
 * acpi_pci_irq_enable
 * success: return 0
 * failure: return < 0
 */

L
Len Brown 已提交
447
int acpi_pci_irq_enable(struct pci_dev *dev)
L
Linus Torvalds 已提交
448
{
449
	struct acpi_prt_entry *entry;
450
	int gsi = 0;
L
Len Brown 已提交
451
	u8 pin = 0;
B
Bob Moore 已提交
452 453
	int triggering = ACPI_LEVEL_SENSITIVE;
	int polarity = ACPI_ACTIVE_LOW;
L
Len Brown 已提交
454
	char *link = NULL;
455
	char link_desc[16];
L
Len Brown 已提交
456
	int rc;
L
Linus Torvalds 已提交
457 458


459
	pin = dev->pin;
L
Linus Torvalds 已提交
460
	if (!pin) {
L
Len Brown 已提交
461 462 463
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "No interrupt pin configured for device %s\n",
				  pci_name(dev)));
464
		return 0;
L
Linus Torvalds 已提交
465 466 467 468 469 470
	}

	/* 
	 * First we check the PCI IRQ routing table (PRT) for an IRQ.  PRT
	 * values override any BIOS-assigned IRQs set during boot.
	 */
471
	entry = acpi_pci_irq_lookup(dev, pin);
L
Linus Torvalds 已提交
472 473 474 475 476

	/*
	 * If no PRT entry was found, we'll try to derive an IRQ from the
	 * device's parent bridge.
	 */
477 478 479 480 481 482 483 484
	if (!entry)
		entry = acpi_pci_irq_derive(dev, pin);

	if (entry)
		gsi = acpi_pci_allocate_irq(entry, &triggering, &polarity,
					    &link);
	else
		gsi = -1;
L
Len Brown 已提交
485

486
	if (gsi < 0) {
487 488 489 490 491 492 493 494
		/*
		 * IDE legacy mode controller IRQs are magic. Why do compat
		 * extensions always make such a nasty mess.
		 */
		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
				(dev->class & 0x05) == 0)
			return 0;
	}
L
Linus Torvalds 已提交
495 496 497 498
	/*
	 * No IRQ known to the ACPI subsystem - maybe the BIOS / 
	 * driver reported one, then use it. Exit in any case.
	 */
499
	if (gsi < 0) {
500
		dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
L
Linus Torvalds 已提交
501
		/* Interrupt Line values above 0xF are forbidden */
502
		if (dev->irq > 0 && (dev->irq <= 0xF)) {
L
Linus Torvalds 已提交
503
			printk(" - using IRQ %d\n", dev->irq);
L
Len Brown 已提交
504 505
			acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
					  ACPI_ACTIVE_LOW);
506
			return 0;
L
Len Brown 已提交
507
		} else {
L
Linus Torvalds 已提交
508
			printk("\n");
509
			return 0;
L
Linus Torvalds 已提交
510
		}
L
Len Brown 已提交
511
	}
L
Linus Torvalds 已提交
512

513
	rc = acpi_register_gsi(gsi, triggering, polarity);
514
	if (rc < 0) {
515
		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
516
			 pin_name(pin));
517
		return rc;
518 519
	}
	dev->irq = rc;
L
Linus Torvalds 已提交
520 521

	if (link)
522 523 524
		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
	else
		link_desc[0] = '\0';
L
Linus Torvalds 已提交
525

526
	dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
527
		 pin_name(pin), link_desc, gsi,
528 529
		 (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
		 (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
L
Linus Torvalds 已提交
530

531
	return 0;
L
Linus Torvalds 已提交
532 533
}

534
/* FIXME: implement x86/x86_64 version */
L
Len Brown 已提交
535 536 537
void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
{
}
538

L
Len Brown 已提交
539
void acpi_pci_irq_disable(struct pci_dev *dev)
L
Linus Torvalds 已提交
540
{
541
	struct acpi_prt_entry *entry;
L
Len Brown 已提交
542 543
	int gsi = 0;
	u8 pin = 0;
L
Linus Torvalds 已提交
544 545


546
	pin = dev->pin;
L
Linus Torvalds 已提交
547
	if (!pin)
548
		return;
L
Linus Torvalds 已提交
549 550 551 552

	/*
	 * First we check the PCI IRQ routing table (PRT) for an IRQ.
	 */
553 554
	entry = acpi_pci_irq_lookup(dev, pin);

L
Linus Torvalds 已提交
555 556 557 558
	/*
	 * If no PRT entry was found, we'll try to derive an IRQ from the
	 * device's parent bridge.
	 */
559 560 561 562
	if (!entry)
		entry = acpi_pci_irq_derive(dev, pin);

	if (!entry)
563
		return;
L
Linus Torvalds 已提交
564

565 566
	gsi = acpi_pci_free_irq(entry);

L
Linus Torvalds 已提交
567 568 569 570 571
	/*
	 * TBD: It might be worth clearing dev->irq by magic constant
	 * (e.g. PCI_UNDEFINED_IRQ).
	 */

572
	dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
L
Linus Torvalds 已提交
573 574
	acpi_unregister_gsi(gsi);
}