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 /drivers/acpi/osl.c | |
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>
Diffstat (limited to 'drivers/acpi/osl.c')
-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 | ||