pci_irq.c 14.8 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 65 66 67
static inline char pin_name(int pin)
{
	return 'A' + pin;
}

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

L
Len Brown 已提交
72 73 74
static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
							  int bus,
							  int device, int pin)
L
Linus Torvalds 已提交
75
{
L
Len Brown 已提交
76
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
77 78

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

	/*
	 * 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);
87
	list_for_each_entry(entry, &acpi_prt.entries, node) {
L
Len Brown 已提交
88 89 90 91
		if ((segment == entry->id.segment)
		    && (bus == entry->id.bus)
		    && (device == entry->id.device)
		    && (pin == entry->pin)) {
L
Linus Torvalds 已提交
92
			spin_unlock(&acpi_prt_lock);
93
			return entry;
L
Linus Torvalds 已提交
94 95 96 97
		}
	}

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

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 150 151 152 153 154
/* 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;
};

/*
 * 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[] = {
	{ medion_md9580, 0, 0, 9, 'A',
155 156
		"\\_SB_.PCI0.ISA_.LNKA",
		"\\_SB_.PCI0.ISA_.LNKB"},
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
	{ dell_optiplex, 0, 0, 0xd, 'A',
		"\\_SB_.LNKB",
		"\\_SB_.LNKA"},
	{ hp_t5710, 0, 0, 1, 'A',
		"\\_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 &&
182
		    pin_name(entry->pin) == quirk->pin &&
183 184 185
		    !strcmp(prt->source, quirk->source) &&
		    strlen(prt->source) >= strlen(quirk->actual_source)) {
			printk(KERN_WARNING PREFIX "firmware reports "
186
				"%04x:%02x:%02x PCI INT %c connected to %s; "
187 188
				"changing to %s\n",
				entry->id.segment, entry->id.bus,
189
				entry->id.device, pin_name(entry->pin),
190 191 192 193 194 195
				prt->source, quirk->actual_source);
			strcpy(prt->source, quirk->actual_source);
		}
	}
}

L
Linus Torvalds 已提交
196
static int
L
Len Brown 已提交
197 198
acpi_pci_irq_add_entry(acpi_handle handle,
		       int segment, int bus, struct acpi_pci_routing_table *prt)
L
Linus Torvalds 已提交
199
{
L
Len Brown 已提交
200
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
201

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

	entry->id.segment = segment;
	entry->id.bus = bus;
	entry->id.device = (prt->address >> 16) & 0xFFFF;
	entry->pin = prt->pin;

211 212
	do_prt_fixups(entry, prt);

L
Linus Torvalds 已提交
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
	/*
	 * 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,
241
			      "      %04x:%02x:%02x[%c] -> %s[%d]\n",
L
Len Brown 已提交
242
			      entry->id.segment, entry->id.bus,
243 244
			      entry->id.device, pin_name(entry->pin),
			      prt->source, entry->link.index));
L
Linus Torvalds 已提交
245 246 247 248 249 250

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

251
	return 0;
L
Linus Torvalds 已提交
252 253 254
}

static void
L
Len Brown 已提交
255
acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry)
L
Linus Torvalds 已提交
256
{
L
Len Brown 已提交
257
	if (segment == entry->id.segment && bus == entry->id.bus) {
L
Linus Torvalds 已提交
258 259 260 261 262 263
		acpi_prt.count--;
		list_del(&entry->node);
		kfree(entry);
	}
}

L
Len Brown 已提交
264
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
L
Linus Torvalds 已提交
265
{
266 267 268
	acpi_status status;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_pci_routing_table *entry;
L
Len Brown 已提交
269
	static int first_time = 1;
L
Linus Torvalds 已提交
270 271 272 273 274 275 276

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

277 278 279 280
	/* '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 已提交
281 282

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

285
	kfree(buffer.pointer);
L
Linus Torvalds 已提交
286

287
	buffer.length = ACPI_ALLOCATE_BUFFER;
L
Linus Torvalds 已提交
288 289 290 291
	buffer.pointer = NULL;

	status = acpi_get_irq_routing_table(handle, &buffer);
	if (ACPI_FAILURE(status)) {
292 293
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
				acpi_format_exception(status)));
L
Linus Torvalds 已提交
294
		kfree(buffer.pointer);
295
		return -ENODEV;
L
Linus Torvalds 已提交
296 297
	}

298
	entry = buffer.pointer;
L
Linus Torvalds 已提交
299 300 301
	while (entry && (entry->length > 0)) {
		acpi_pci_irq_add_entry(handle, segment, bus, entry);
		entry = (struct acpi_pci_routing_table *)
L
Len Brown 已提交
302
		    ((unsigned long)entry + entry->length);
L
Linus Torvalds 已提交
303 304
	}

305
	kfree(buffer.pointer);
306
	return 0;
L
Linus Torvalds 已提交
307 308
}

L
Len Brown 已提交
309
void acpi_pci_irq_del_prt(int segment, int bus)
L
Linus Torvalds 已提交
310
{
L
Len Brown 已提交
311 312
	struct list_head *node = NULL, *n = NULL;
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
313

L
Len Brown 已提交
314
	if (!acpi_prt.count) {
L
Linus Torvalds 已提交
315 316 317
		return;
	}

L
Len Brown 已提交
318
	printk(KERN_DEBUG
319 320
	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
	       segment, bus);
L
Linus Torvalds 已提交
321 322 323 324 325 326 327 328
	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 已提交
329

L
Linus Torvalds 已提交
330 331 332
/* --------------------------------------------------------------------------
                          PCI Interrupt Routing Support
   -------------------------------------------------------------------------- */
L
Len Brown 已提交
333
typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **);
L
Linus Torvalds 已提交
334

335 336
static int
acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
B
Bob Moore 已提交
337
		      int *triggering, int *polarity, char **link)
338
{
L
Len Brown 已提交
339
	int irq;
340 341 342 343


	if (entry->link.handle) {
		irq = acpi_pci_link_allocate_irq(entry->link.handle,
B
Bob Moore 已提交
344 345
						 entry->link.index, triggering,
						 polarity, link);
346
		if (irq < 0) {
347 348
			printk(KERN_WARNING PREFIX
				      "Invalid IRQ link routing entry\n");
349
			return -1;
350 351 352
		}
	} else {
		irq = entry->link.index;
B
Bob Moore 已提交
353 354
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
355 356
	}

357
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found GSI %d\n", irq));
358
	return irq;
359 360 361 362
}

static int
acpi_pci_free_irq(struct acpi_prt_entry *entry,
B
Bob Moore 已提交
363
		  int *triggering, int *polarity, char **link)
364
{
L
Len Brown 已提交
365
	int irq;
366 367 368 369 370 371

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

L
Linus Torvalds 已提交
375 376 377 378 379 380
/*
 * acpi_pci_irq_lookup
 * success: return IRQ >= 0
 * failure: return -1
 */
static int
L
Len Brown 已提交
381 382 383
acpi_pci_irq_lookup(struct pci_bus *bus,
		    int device,
		    int pin,
B
Bob Moore 已提交
384 385
		    int *triggering,
		    int *polarity, char **link, irq_lookup_func func)
L
Linus Torvalds 已提交
386
{
L
Len Brown 已提交
387
	struct acpi_prt_entry *entry = NULL;
L
Linus Torvalds 已提交
388 389
	int segment = pci_domain_nr(bus);
	int bus_nr = bus->number;
390
	int ret;
L
Linus Torvalds 已提交
391 392


L
Len Brown 已提交
393
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
394
			  "Searching for _PRT entry for %04x:%02x:%02x[%c]\n",
395
			  segment, bus_nr, device, pin_name(pin)));
L
Linus Torvalds 已提交
396

L
Len Brown 已提交
397
	entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
L
Linus Torvalds 已提交
398
	if (!entry) {
399
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_PRT entry not found\n"));
400
		return -1;
L
Linus Torvalds 已提交
401
	}
L
Len Brown 已提交
402

B
Bob Moore 已提交
403
	ret = func(entry, triggering, polarity, link);
404
	return ret;
L
Linus Torvalds 已提交
405 406 407 408 409 410 411 412
}

/*
 * acpi_pci_irq_derive
 * success: return IRQ >= 0
 * failure: return < 0
 */
static int
L
Len Brown 已提交
413 414
acpi_pci_irq_derive(struct pci_dev *dev,
		    int pin,
B
Bob Moore 已提交
415 416
		    int *triggering,
		    int *polarity, char **link, irq_lookup_func func)
L
Linus Torvalds 已提交
417
{
L
Len Brown 已提交
418 419
	struct pci_dev *bridge = dev;
	int irq = -1;
420
	u8 bridge_pin = 0, orig_pin = pin;
L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432


	/* 
	 * 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).
	 */
	while (irq < 0 && bridge->bus->self) {
		pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
		bridge = bridge->bus->self;

		if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
			/* PC card has the same IRQ as its cardbridge */
433
			bridge_pin = bridge->pin;
L
Linus Torvalds 已提交
434
			if (!bridge_pin) {
L
Len Brown 已提交
435 436 437
				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
						  "No interrupt pin configured for device %s\n",
						  pci_name(bridge)));
438
				return -1;
L
Linus Torvalds 已提交
439 440
			}
			/* Pin is from 0 to 3 */
L
Len Brown 已提交
441
			bridge_pin--;
L
Linus Torvalds 已提交
442 443 444 445
			pin = bridge_pin;
		}

		irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
B
Bob Moore 已提交
446
					  pin, triggering, polarity,
L
Len Brown 已提交
447
					  link, func);
L
Linus Torvalds 已提交
448 449 450
	}

	if (irq < 0) {
451
		dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
452
			 pin_name(orig_pin));
453
		return -1;
L
Linus Torvalds 已提交
454 455
	}

456
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive GSI %d for device %s from %s\n",
L
Len Brown 已提交
457
			  irq, pci_name(dev), pci_name(bridge)));
L
Linus Torvalds 已提交
458

459
	return irq;
L
Linus Torvalds 已提交
460 461 462 463 464 465 466 467
}

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

L
Len Brown 已提交
468
int acpi_pci_irq_enable(struct pci_dev *dev)
L
Linus Torvalds 已提交
469
{
470
	int gsi = 0;
L
Len Brown 已提交
471
	u8 pin = 0;
B
Bob Moore 已提交
472 473
	int triggering = ACPI_LEVEL_SENSITIVE;
	int polarity = ACPI_ACTIVE_LOW;
L
Len Brown 已提交
474
	char *link = NULL;
475
	char link_desc[16];
L
Len Brown 已提交
476
	int rc;
L
Linus Torvalds 已提交
477 478


479
	pin = dev->pin;
L
Linus Torvalds 已提交
480
	if (!pin) {
L
Len Brown 已提交
481 482 483
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "No interrupt pin configured for device %s\n",
				  pci_name(dev)));
484
		return 0;
L
Linus Torvalds 已提交
485 486 487 488 489 490 491
	}
	pin--;

	/* 
	 * First we check the PCI IRQ routing table (PRT) for an IRQ.  PRT
	 * values override any BIOS-assigned IRQs set during boot.
	 */
492
	gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
B
Bob Moore 已提交
493
				  &triggering, &polarity, &link,
L
Len Brown 已提交
494
				  acpi_pci_allocate_irq);
L
Linus Torvalds 已提交
495 496 497 498 499

	/*
	 * If no PRT entry was found, we'll try to derive an IRQ from the
	 * device's parent bridge.
	 */
500 501
	if (gsi < 0)
		gsi = acpi_pci_irq_derive(dev, pin, &triggering,
B
Bob Moore 已提交
502
					  &polarity, &link,
L
Len Brown 已提交
503 504
					  acpi_pci_allocate_irq);

505
	if (gsi < 0) {
506 507 508 509 510 511 512 513
		/*
		 * 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 已提交
514 515 516 517
	/*
	 * No IRQ known to the ACPI subsystem - maybe the BIOS / 
	 * driver reported one, then use it. Exit in any case.
	 */
518
	if (gsi < 0) {
519
		dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
L
Linus Torvalds 已提交
520
		/* Interrupt Line values above 0xF are forbidden */
521
		if (dev->irq > 0 && (dev->irq <= 0xF)) {
L
Linus Torvalds 已提交
522
			printk(" - using IRQ %d\n", dev->irq);
L
Len Brown 已提交
523 524
			acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
					  ACPI_ACTIVE_LOW);
525
			return 0;
L
Len Brown 已提交
526
		} else {
L
Linus Torvalds 已提交
527
			printk("\n");
528
			return 0;
L
Linus Torvalds 已提交
529
		}
L
Len Brown 已提交
530
	}
L
Linus Torvalds 已提交
531

532
	rc = acpi_register_gsi(gsi, triggering, polarity);
533
	if (rc < 0) {
534
		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
535
			 pin_name(pin));
536
		return rc;
537 538
	}
	dev->irq = rc;
L
Linus Torvalds 已提交
539 540

	if (link)
541 542 543
		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
	else
		link_desc[0] = '\0';
L
Linus Torvalds 已提交
544

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

550
	return 0;
L
Linus Torvalds 已提交
551 552
}

553
/* FIXME: implement x86/x86_64 version */
L
Len Brown 已提交
554 555 556
void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
{
}
557

L
Len Brown 已提交
558
void acpi_pci_irq_disable(struct pci_dev *dev)
L
Linus Torvalds 已提交
559
{
L
Len Brown 已提交
560 561
	int gsi = 0;
	u8 pin = 0;
B
Bob Moore 已提交
562 563
	int triggering = ACPI_LEVEL_SENSITIVE;
	int polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
564 565


566
	pin = dev->pin;
L
Linus Torvalds 已提交
567
	if (!pin)
568
		return;
L
Linus Torvalds 已提交
569 570 571 572 573
	pin--;

	/*
	 * First we check the PCI IRQ routing table (PRT) for an IRQ.
	 */
L
Len Brown 已提交
574
	gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
B
Bob Moore 已提交
575
				  &triggering, &polarity, NULL,
L
Len Brown 已提交
576
				  acpi_pci_free_irq);
L
Linus Torvalds 已提交
577 578 579 580 581
	/*
	 * If no PRT entry was found, we'll try to derive an IRQ from the
	 * device's parent bridge.
	 */
	if (gsi < 0)
L
Len Brown 已提交
582
		gsi = acpi_pci_irq_derive(dev, pin,
B
Bob Moore 已提交
583
					  &triggering, &polarity, NULL,
L
Len Brown 已提交
584
					  acpi_pci_free_irq);
L
Linus Torvalds 已提交
585
	if (gsi < 0)
586
		return;
L
Linus Torvalds 已提交
587 588 589 590 591 592

	/*
	 * TBD: It might be worth clearing dev->irq by magic constant
	 * (e.g. PCI_UNDEFINED_IRQ).
	 */

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