diff options
author | Len Brown <len.brown@intel.com> | 2005-07-29 23:31:17 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-07-29 23:31:17 -0400 |
commit | d6ac1a7910d22626bc77e73db091e00b810715f4 (patch) | |
tree | c8f235b7287056a03bc2bc032902469a331b5e56 /drivers/acpi/pci_irq.c | |
parent | 577a4f8102d54b504cb22eb021b89e957e8df18f (diff) | |
parent | 87bec66b9691522414862dd8d41e430b063735ef (diff) |
/home/lenb/src/to-linus branch 'acpi-2.6.12'
Diffstat (limited to 'drivers/acpi/pci_irq.c')
-rw-r--r-- | drivers/acpi/pci_irq.c | 85 |
1 files changed, 59 insertions, 26 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index d1f42b972821..bb973d2109a1 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus) | |||
269 | /* -------------------------------------------------------------------------- | 269 | /* -------------------------------------------------------------------------- |
270 | PCI Interrupt Routing Support | 270 | PCI Interrupt Routing Support |
271 | -------------------------------------------------------------------------- */ | 271 | -------------------------------------------------------------------------- */ |
272 | typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); | ||
272 | 273 | ||
274 | static int | ||
275 | acpi_pci_allocate_irq(struct acpi_prt_entry *entry, | ||
276 | int *edge_level, | ||
277 | int *active_high_low, | ||
278 | char **link) | ||
279 | { | ||
280 | int irq; | ||
281 | |||
282 | ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); | ||
283 | |||
284 | if (entry->link.handle) { | ||
285 | irq = acpi_pci_link_allocate_irq(entry->link.handle, | ||
286 | entry->link.index, edge_level, active_high_low, link); | ||
287 | if (irq < 0) { | ||
288 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); | ||
289 | return_VALUE(-1); | ||
290 | } | ||
291 | } else { | ||
292 | irq = entry->link.index; | ||
293 | *edge_level = ACPI_LEVEL_SENSITIVE; | ||
294 | *active_high_low = ACPI_ACTIVE_LOW; | ||
295 | } | ||
296 | |||
297 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | ||
298 | return_VALUE(irq); | ||
299 | } | ||
300 | |||
301 | static int | ||
302 | acpi_pci_free_irq(struct acpi_prt_entry *entry, | ||
303 | int *edge_level, | ||
304 | int *active_high_low, | ||
305 | char **link) | ||
306 | { | ||
307 | int irq; | ||
308 | |||
309 | ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); | ||
310 | if (entry->link.handle) { | ||
311 | irq = acpi_pci_link_free_irq(entry->link.handle); | ||
312 | } else { | ||
313 | irq = entry->link.index; | ||
314 | } | ||
315 | return_VALUE(irq); | ||
316 | } | ||
273 | /* | 317 | /* |
274 | * acpi_pci_irq_lookup | 318 | * acpi_pci_irq_lookup |
275 | * success: return IRQ >= 0 | 319 | * success: return IRQ >= 0 |
@@ -282,12 +326,13 @@ acpi_pci_irq_lookup ( | |||
282 | int pin, | 326 | int pin, |
283 | int *edge_level, | 327 | int *edge_level, |
284 | int *active_high_low, | 328 | int *active_high_low, |
285 | char **link) | 329 | char **link, |
330 | irq_lookup_func func) | ||
286 | { | 331 | { |
287 | struct acpi_prt_entry *entry = NULL; | 332 | struct acpi_prt_entry *entry = NULL; |
288 | int segment = pci_domain_nr(bus); | 333 | int segment = pci_domain_nr(bus); |
289 | int bus_nr = bus->number; | 334 | int bus_nr = bus->number; |
290 | int irq; | 335 | int ret; |
291 | 336 | ||
292 | ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); | 337 | ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); |
293 | 338 | ||
@@ -301,22 +346,8 @@ acpi_pci_irq_lookup ( | |||
301 | return_VALUE(-1); | 346 | return_VALUE(-1); |
302 | } | 347 | } |
303 | 348 | ||
304 | if (entry->link.handle) { | 349 | ret = func(entry, edge_level, active_high_low, link); |
305 | irq = acpi_pci_link_get_irq(entry->link.handle, | 350 | return_VALUE(ret); |
306 | entry->link.index, edge_level, active_high_low, link); | ||
307 | if (irq < 0) { | ||
308 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); | ||
309 | return_VALUE(-1); | ||
310 | } | ||
311 | } else { | ||
312 | irq = entry->link.index; | ||
313 | *edge_level = ACPI_LEVEL_SENSITIVE; | ||
314 | *active_high_low = ACPI_ACTIVE_LOW; | ||
315 | } | ||
316 | |||
317 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | ||
318 | |||
319 | return_VALUE(irq); | ||
320 | } | 351 | } |
321 | 352 | ||
322 | /* | 353 | /* |
@@ -330,7 +361,8 @@ acpi_pci_irq_derive ( | |||
330 | int pin, | 361 | int pin, |
331 | int *edge_level, | 362 | int *edge_level, |
332 | int *active_high_low, | 363 | int *active_high_low, |
333 | char **link) | 364 | char **link, |
365 | irq_lookup_func func) | ||
334 | { | 366 | { |
335 | struct pci_dev *bridge = dev; | 367 | struct pci_dev *bridge = dev; |
336 | int irq = -1; | 368 | int irq = -1; |
@@ -363,7 +395,7 @@ acpi_pci_irq_derive ( | |||
363 | } | 395 | } |
364 | 396 | ||
365 | irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), | 397 | irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), |
366 | pin, edge_level, active_high_low, link); | 398 | pin, edge_level, active_high_low, link, func); |
367 | } | 399 | } |
368 | 400 | ||
369 | if (irq < 0) { | 401 | if (irq < 0) { |
@@ -415,7 +447,7 @@ acpi_pci_irq_enable ( | |||
415 | * values override any BIOS-assigned IRQs set during boot. | 447 | * values override any BIOS-assigned IRQs set during boot. |
416 | */ | 448 | */ |
417 | irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | 449 | irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, |
418 | &edge_level, &active_high_low, &link); | 450 | &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); |
419 | 451 | ||
420 | /* | 452 | /* |
421 | * If no PRT entry was found, we'll try to derive an IRQ from the | 453 | * If no PRT entry was found, we'll try to derive an IRQ from the |
@@ -423,7 +455,7 @@ acpi_pci_irq_enable ( | |||
423 | */ | 455 | */ |
424 | if (irq < 0) | 456 | if (irq < 0) |
425 | irq = acpi_pci_irq_derive(dev, pin, &edge_level, | 457 | irq = acpi_pci_irq_derive(dev, pin, &edge_level, |
426 | &active_high_low, &link); | 458 | &active_high_low, &link, acpi_pci_allocate_irq); |
427 | 459 | ||
428 | /* | 460 | /* |
429 | * No IRQ known to the ACPI subsystem - maybe the BIOS / | 461 | * No IRQ known to the ACPI subsystem - maybe the BIOS / |
@@ -462,7 +494,9 @@ acpi_pci_irq_enable ( | |||
462 | EXPORT_SYMBOL(acpi_pci_irq_enable); | 494 | EXPORT_SYMBOL(acpi_pci_irq_enable); |
463 | 495 | ||
464 | 496 | ||
465 | #ifdef CONFIG_ACPI_DEALLOCATE_IRQ | 497 | /* FIXME: implement x86/x86_64 version */ |
498 | void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} | ||
499 | |||
466 | void | 500 | void |
467 | acpi_pci_irq_disable ( | 501 | acpi_pci_irq_disable ( |
468 | struct pci_dev *dev) | 502 | struct pci_dev *dev) |
@@ -489,14 +523,14 @@ acpi_pci_irq_disable ( | |||
489 | * First we check the PCI IRQ routing table (PRT) for an IRQ. | 523 | * First we check the PCI IRQ routing table (PRT) for an IRQ. |
490 | */ | 524 | */ |
491 | gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | 525 | gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, |
492 | &edge_level, &active_high_low, NULL); | 526 | &edge_level, &active_high_low, NULL, acpi_pci_free_irq); |
493 | /* | 527 | /* |
494 | * If no PRT entry was found, we'll try to derive an IRQ from the | 528 | * If no PRT entry was found, we'll try to derive an IRQ from the |
495 | * device's parent bridge. | 529 | * device's parent bridge. |
496 | */ | 530 | */ |
497 | if (gsi < 0) | 531 | if (gsi < 0) |
498 | gsi = acpi_pci_irq_derive(dev, pin, | 532 | gsi = acpi_pci_irq_derive(dev, pin, |
499 | &edge_level, &active_high_low, NULL); | 533 | &edge_level, &active_high_low, NULL, acpi_pci_free_irq); |
500 | if (gsi < 0) | 534 | if (gsi < 0) |
501 | return_VOID; | 535 | return_VOID; |
502 | 536 | ||
@@ -512,4 +546,3 @@ acpi_pci_irq_disable ( | |||
512 | 546 | ||
513 | return_VOID; | 547 | return_VOID; |
514 | } | 548 | } |
515 | #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ | ||