diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-08 17:48:16 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-24 13:59:00 -0500 |
| commit | 23fe36306ea489eef7dd88506bdcefdc8da39c91 (patch) | |
| tree | e788dffdc10ae283f737604f7cb476c13bcc1bce | |
| parent | 2aa15890f3c191326678f1bd68af61ec6b8753ec (diff) | |
ACPI: Avoid calling request_irq() many times for the same interrupt
In principle acpi_os_install_interrupt_handler() may be called
multiple times for different interrupts, either from
acpi_ev_get_gpe_xrupt_block(), or from acpi_ev_install_sci_handler().
However, it always attempts to request the same interrupt,
acpi_gbl_FADT.sci_interrupt and it doesn't check whether or not this
interrupt has already been requested.
Modify this function so that it refuses to request interrupts other
than acpi_gbl_FADT.sci_interrupt and change
acpi_os_remove_interrupt_handler() so that it refuses to free such
interrupts. Use the observation that the only supported ACPI
interrupt must be equal to acpi_gbl_FADT.sci_interrupt and drop an
unnecessary variable acpi_irq_irq.
This change has been tested on Toshiba Portege R500 and HP nx6325
without introducing any visible problems.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
| -rw-r--r-- | drivers/acpi/osl.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c90c76aa7f8b..187dff96356b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -76,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger); | |||
| 76 | extern char line_buf[80]; | 76 | extern char line_buf[80]; |
| 77 | #endif /*ENABLE_DEBUGGER */ | 77 | #endif /*ENABLE_DEBUGGER */ |
| 78 | 78 | ||
| 79 | static unsigned int acpi_irq_irq; | ||
| 80 | static acpi_osd_handler acpi_irq_handler; | 79 | static acpi_osd_handler acpi_irq_handler; |
| 81 | static void *acpi_irq_context; | 80 | static void *acpi_irq_context; |
| 82 | static struct workqueue_struct *kacpid_wq; | 81 | static struct workqueue_struct *kacpid_wq; |
| @@ -516,11 +515,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
| 516 | acpi_irq_stats_init(); | 515 | acpi_irq_stats_init(); |
| 517 | 516 | ||
| 518 | /* | 517 | /* |
| 519 | * Ignore the GSI from the core, and use the value in our copy of the | 518 | * ACPI interrupts different from the SCI in our copy of the FADT are |
| 520 | * FADT. It may not be the same if an interrupt source override exists | 519 | * not supported. |
| 521 | * for the SCI. | ||
| 522 | */ | 520 | */ |
| 523 | gsi = acpi_gbl_FADT.sci_interrupt; | 521 | if (gsi != acpi_gbl_FADT.sci_interrupt) |
| 522 | return AE_BAD_PARAMETER; | ||
| 523 | |||
| 524 | if (acpi_irq_handler) | ||
| 525 | return AE_ALREADY_ACQUIRED; | ||
| 526 | |||
| 524 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { | 527 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { |
| 525 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", | 528 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", |
| 526 | gsi); | 529 | gsi); |
| @@ -531,20 +534,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
| 531 | acpi_irq_context = context; | 534 | acpi_irq_context = context; |
| 532 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { | 535 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { |
| 533 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); | 536 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); |
| 537 | acpi_irq_handler = NULL; | ||
| 534 | return AE_NOT_ACQUIRED; | 538 | return AE_NOT_ACQUIRED; |
| 535 | } | 539 | } |
| 536 | acpi_irq_irq = irq; | ||
| 537 | 540 | ||
| 538 | return AE_OK; | 541 | return AE_OK; |
| 539 | } | 542 | } |
| 540 | 543 | ||
| 541 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) | 544 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) |
| 542 | { | 545 | { |
| 543 | if (irq) { | 546 | if (irq != acpi_gbl_FADT.sci_interrupt) |
| 544 | free_irq(irq, acpi_irq); | 547 | return AE_BAD_PARAMETER; |
| 545 | acpi_irq_handler = NULL; | 548 | |
| 546 | acpi_irq_irq = 0; | 549 | free_irq(irq, acpi_irq); |
| 547 | } | 550 | acpi_irq_handler = NULL; |
| 548 | 551 | ||
| 549 | return AE_OK; | 552 | return AE_OK; |
| 550 | } | 553 | } |
| @@ -1603,7 +1606,7 @@ acpi_status __init acpi_os_initialize1(void) | |||
| 1603 | acpi_status acpi_os_terminate(void) | 1606 | acpi_status acpi_os_terminate(void) |
| 1604 | { | 1607 | { |
| 1605 | if (acpi_irq_handler) { | 1608 | if (acpi_irq_handler) { |
| 1606 | acpi_os_remove_interrupt_handler(acpi_irq_irq, | 1609 | acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt, |
| 1607 | acpi_irq_handler); | 1610 | acpi_irq_handler); |
| 1608 | } | 1611 | } |
| 1609 | 1612 | ||
