failure of acpi_register_gsi() should be handled properly
Subsystems (5)
cover failure of acpi_register_gsi() should be handled properly
Hi,
Current acpi_register_gsi() function has no way to indicate errors to its callers even though acpi_register_gsi() can fail to register gsi because of some reasons (out of memory, lack of interrupt vectors, incorrect BIOS, and so on). As a result, caller of acpi_register_gsi() cannot handle the case that acpi_register_gsi() fails. I think failure of acpi_register_gsi() should be handled properly.
This series of patches changes acpi_register_gsi() to return negative value on error, and also changes callers of acpi_register_gsi() to handle failure of acpi_register_gsi().
Thanks,
Kenji Kaneshige
PATCH 1/6 failure of acpi_register_gsi() should be handled properly - change acpi_register_gsi() interface
This patch changes the type of return value of acpi_register_gsi() from "unsigned int" to "int" to indicate an error. If acpi_register_gsi() fails to register gsi, it returns negative value.
---
linux-2.6.13-rc3-kanesige/arch/i386/kernel/acpi/boot.c | 6 +++++- linux-2.6.13-rc3-kanesige/arch/ia64/kernel/acpi.c | 6 +++++- linux-2.6.13-rc3-kanesige/include/linux/acpi.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-)
arch/i386/kernel/acpi/boot.c renamed from arch/i386/kernel/acpi/boot.c~handle-error-acpi_register_gsi +5 -1
@@ -484,7 +484,11 @@ int acpi_gsi_to_irq(u32 gsi, unsigned inreturn 0 ; } -unsigned int acpi_register_gsi (u32 gsi,int edge_level,int active_high_low) +/* +* success: return IRQ number (>=0) +* failure: return < 0 +*/ +int acpi_register_gsi (u32 gsi,int edge_level,int active_high_low) {unsigned int irq;unsigned int plat_gsi = gsi;
arch/ia64/kernel/acpi.c renamed from arch/ia64/kernel/acpi.c~handle-error-acpi_register_gsi +5 -1
@@ -563,7 +563,11 @@ acpi_numa_arch_fixup (void) }#endif /* CONFIG_ACPI_NUMA */ -unsigned int +/* +* success: return IRQ number (>=0) +* failure: return < 0 +*/ +int acpi_register_gsi (u32 gsi,int edge_level,int active_high_low) {if (has_8259 && gsi <16 )
include/linux/acpi.h renamed from include/linux/acpi.h~handle-error-acpi_register_gsi +1 -1
@@ -445,7 +445,7 @@ static inline int acpi_boot_table_init(v#endif /*!CONFIG_ACPI_BOOT*/ -unsigned int acpi_register_gsi (u32 gsi,int edge_level,int active_high_low); +int acpi_register_gsi (u32 gsi,int edge_level,int active_high_low);int acpi_gsi_to_irq (u32 gsi,unsigned int *irq);/*
_
PATCH 2/6 failure of acpi_register_gsi() should be handled properly - change acpi pci code
In reply to Kenji KaneshigeThis patch adds the error check of acpi_register_gsi() into acpi_pci_enable_irq().
---
linux-2.6.13-rc3-kanesige/drivers/acpi/pci_irq.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletion(-)
drivers/acpi/pci_irq.c renamed from drivers/acpi/pci_irq.c~handle-error-acpi_register_gsi-acpi_pci_enable_irq +8 -1
@@ -392,6 +392,7 @@ acpi_pci_irq_enable (int edge_level =ACPI_LEVEL_SENSITIVE ;int active_high_low =ACPI_ACTIVE_LOW ;char *link =NULL ; +int rc;ACPI_FUNCTION_TRACE ("acpi_pci_irq_enable" );
@@ -444,7 +445,13 @@ acpi_pci_irq_enable ( } } - dev->irq =acpi_register_gsi (irq, edge_level, active_high_low); + rc =acpi_register_gsi (irq, edge_level, active_high_low); +if (rc <0 ) { + printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed " + "to register GSI\n", pci_name(dev), ('A' + pin)); +return_VALUE (rc); + } + dev->irq = rc; printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", pci_name(dev), 'A' + pin);
_
PATCH 3/6 failure of acpi_register_gsi() should be handled properly - change hpet driver
In reply to Kenji KaneshigeThis patch adds the error check of acpi_register_gsi() into hpet driver.
---
linux-2.6.13-rc3-kanesige/drivers/char/hpet.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
drivers/char/hpet.c renamed from drivers/char/hpet.c~handle-error-acpi_register_gsi-hpet +5 -2
@@ -906,11 +906,15 @@ static acpi_status hpet_resources(structif (irqp->number_of_interrupts >0 ) { hdp->hd_nirqs = irqp->number_of_interrupts; -for (i =0 ; i < hdp->hd_nirqs; i++) - hdp->hd_irq[i] + for (i = 0; i < hdp->hd_nirqs; i++) { + int rc acpi_register_gsi(irqp->interrupts[i], irqp->edge_level, irqp->active_high_low); +if (rc <0 ) +return AE_ERROR ; + hdp->hd_irq[i] = rc; + } } }
_
PATCH 4/6 failure of acpi_register_gsi() should be handled properly - change phpacpi driver
In reply to Kenji KaneshigeThis patch adds the error check of acpi_register_gsi() into pnpacpi driver.
---
linux-2.6.13-rc3-kanesige/drivers/pnp/pnpacpi/rsparser.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/pnp/pnpacpi/rsparser.c renamed from drivers/pnp/pnpacpi/rsparser.c~handle-error-acpi_register_gsi-pnpacpi +1 -1
@@ -81,7 +81,7 @@ pnpacpi_parse_allocated_irqresource(stru i++;if (i <PNP_MAX_IRQ ) { res->irq_resource[i].flags =IORESOURCE_IRQ ;//Also clears _UNSET flag -if (irq =-1 ) { +if (irq <0 ) { res->irq_resource[i].flags |=IORESOURCE_DISABLED ;return ; }
_
PATCH 5/6 failure of acpi_register_gsi() should be handled properly - change acpi based 8250 driver
In reply to Kenji KaneshigeThis patch adds the error check of acpi_register_gsi() into ACPI based 8250 serial driver.
---
linux-2.6.13-rc3-kanesige/drivers/serial/8250_acpi.c | 20 +++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-)
drivers/serial/8250_acpi.c renamed from drivers/serial/8250_acpi.c~handle-error-acpi_register_gsi-8250_acpi +16 -4
@@ -47,18 +47,30 @@ static acpi_status acpi_serial_port(strustatic acpi_status acpi_serial_ext_irq (struct uart_port *port,struct acpi_resource_ext_irq *ext_irq) { -if (ext_irq->number_of_interrupts >0 ) - port->irq =acpi_register_gsi (ext_irq->interrupts[0 ], +int rc; + +if (ext_irq->number_of_interrupts >0 ) { + rc =acpi_register_gsi (ext_irq->interrupts[0 ], ext_irq->edge_level, ext_irq->active_high_low); +if (rc <0 ) +return AE_ERROR ; + port->irq = rc; + }return AE_OK ; }static acpi_status acpi_serial_irq (struct uart_port *port,struct acpi_resource_irq *irq) { -if (irq->number_of_interrupts >0 ) - port->irq =acpi_register_gsi (irq->interrupts[0 ], +int rc; + +if (irq->number_of_interrupts >0 ) { + rc =acpi_register_gsi (irq->interrupts[0 ], irq->edge_level, irq->active_high_low); +if (rc <0 ) +return AE_ERROR ; + port->irq = rc; + }return AE_OK ; }
_
PATCH 6/6 failure of acpi_register_gsi() should be handled properly - change ia64 iosapic code
In reply to Kenji KaneshigeChange iosapic_register_intr(), which called by acpi_register_gsi(), to return negative value on error instead of panic.
---
linux-2.6.13-rc3-kanesige/arch/ia64/kernel/iosapic.c | 20 ++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-)
arch/ia64/kernel/iosapic.c renamed from arch/ia64/kernel/iosapic.c~handle-error-acpi_register_gsi-remove-panic-iosapic-ia64 +13 -7
@@ -561,7 +561,7 @@ static inline int vector_is_shared (intreturn (iosapic_intr_info[vector].count >1 ); } -static void +static int register_intr (unsigned int gsi,int vector,unsigned char delivery,unsigned long polarity,unsigned long trigger) {
@@ -576,7 +576,7 @@ register_intr (unsigned int gsi, int vec index =find_iosapic (gsi);if (index <0 ) {printk (KERN_WARNING "%s: No IOSAPIC for GSI %u\n" , __FUNCTION__, gsi); -return ; +return -ENODEV ; } iosapic_address = iosapic_lists[index].addr;
@@ -587,7 +587,7 @@ register_intr (unsigned int gsi, int vec rte =iosapic_alloc_rte ();if (!rte) {printk (KERN_WARNING "%s: cannot allocate memory\n" , __FUNCTION__); -return ; +return -ENOMEM ; } rte_index = gsi - gsi_base;
@@ -603,7 +603,7 @@ register_intr (unsigned int gsi, int vecstruct iosapic_intr_info *info = &iosapic_intr_info[vector];if (info->trigger != trigger || info->polarity != polarity) {printk (KERN_WARNING "%s: cannot override the interrupt\n" , __FUNCTION__); -return ; +return -EINVAL ; } }
@@ -623,6 +623,7 @@ register_intr (unsigned int gsi, int vec __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); idesc->handler = irq_type; } +return 0 ; } static unsigned int
@@ -710,7 +711,7 @@ int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int vector, mask = 1; + int vector, mask = 1, err;unsigned int dest;unsigned long flags;struct iosapic_rte_info *rte;
@@ -738,7 +739,7 @@ again:if (vector <0 ) { vector =iosapic_find_sharable_vector (trigger, polarity);if (vector <0 ) -panic ("%s: out of interrupt vectors!\n" , __FUNCTION__); +return -ENOSPC ; }spin_lock_irqsave (&irq_descp (vector)->lock, flags);
@@ -753,8 +754,13 @@ again: } dest =get_target_cpu (gsi, vector); -register_intr (gsi, vector,IOSAPIC_LOWEST_PRIORITY , + err =register_intr (gsi, vector,IOSAPIC_LOWEST_PRIORITY , polarity, trigger); +if (err <0 ) { +spin_unlock (&iosapic_lock); +spin_unlock_irqrestore (&irq_descp (vector)->lock, flags); +return err; + }/* * If the vector is shared and already unmasked for
_