tree d5133cd1d506c77659fa0f9781bf67630f342884
parent 5f0110f2a716376f3b260703835f527ca8900946
author Bjorn Helgaas <[EMAIL PROTECTED]> Sat, 03 Sep 2005 08:37:56 -0400
committer Len Brown <[EMAIL PROTECTED]> Sat, 03 Sep 2005 08:42:56 -0400

[ACPI] PNPACPI IRQ workaround for HP workstations

Move pcibios_penalize_isa_irq() to pnpacpi_parse_allocated_irqresource().
Previously we passed the GSI, not the IRQ, and we did it even if parsing
the IRQ resource failed.

Parse IRQ descriptors that contain multiple interrupts.  This violates the
spec (in _CRS, only one interrupt per descriptor is allowed), but some
firmware, e.g., HP rx7620 and rx8620 descriptions of HPET, has this bug.

Signed-off-by: Bjorn Helgaas <[EMAIL PROTECTED]>
Cc: Adam Belay <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Len Brown <[EMAIL PROTECTED]>

 drivers/pnp/pnpacpi/rsparser.c |   75 +++++++++++++++++++++++------------------
 1 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -73,25 +73,35 @@ static void decode_irq_flags(int flag, i
 }
 
 static void
-pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
+       int edge_level, int active_high_low)
 {
        int i = 0;
+       int irq;
+
+       if (!valid_IRQ(gsi))
+               return;
+
        while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
                        i < PNP_MAX_IRQ)
                i++;
-       if (i < PNP_MAX_IRQ) {
-               res->irq_resource[i].flags = IORESOURCE_IRQ;  //Also clears 
_UNSET flag
-               if (irq < 0) {
-                       res->irq_resource[i].flags |= IORESOURCE_DISABLED;
-                       return;
-               }
-               res->irq_resource[i].start =(unsigned long) irq;
-               res->irq_resource[i].end = (unsigned long) irq;
+       if (i >= PNP_MAX_IRQ)
+               return;
+
+       res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+       irq = acpi_register_gsi(gsi, edge_level, active_high_low);
+       if (irq < 0) {
+               res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+               return;
        }
+
+       res->irq_resource[i].start = irq;
+       res->irq_resource[i].end = irq;
+       pcibios_penalize_isa_irq(irq, 1);
 }
 
 static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
 {
        int i = 0;
        while (i < PNP_MAX_DMA &&
@@ -103,14 +113,14 @@ pnpacpi_parse_allocated_dmaresource(stru
                        res->dma_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
                }
-               res->dma_resource[i].start =(unsigned long) dma;
-               res->dma_resource[i].end = (unsigned long) dma;
+               res->dma_resource[i].start = dma;
+               res->dma_resource[i].end = dma;
        }
 }
 
 static void
 pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
-       int io, int len)
+       u32 io, u32 len)
 {
        int i = 0;
        while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -122,14 +132,14 @@ pnpacpi_parse_allocated_ioresource(struc
                        res->port_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
                }
-               res->port_resource[i].start = (unsigned long) io;
-               res->port_resource[i].end = (unsigned long)(io + len - 1);
+               res->port_resource[i].start = io;
+               res->port_resource[i].end = io + len - 1;
        }
 }
 
 static void
 pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
-       int mem, int len)
+       u64 mem, u64 len)
 {
        int i = 0;
        while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -141,8 +151,8 @@ pnpacpi_parse_allocated_memresource(stru
                        res->mem_resource[i].flags |= IORESOURCE_DISABLED;
                        return;
                }
-               res->mem_resource[i].start = (unsigned long) mem;
-               res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+               res->mem_resource[i].start = mem;
+               res->mem_resource[i].end = mem + len - 1;
        }
 }
 
@@ -151,27 +161,28 @@ static acpi_status pnpacpi_allocated_res
        void *data)
 {
        struct pnp_resource_table * res_table = (struct pnp_resource_table 
*)data;
+       int i;
 
        switch (res->id) {
        case ACPI_RSTYPE_IRQ:
-               if ((res->data.irq.number_of_interrupts > 0) &&
-                       valid_IRQ(res->data.irq.interrupts[0])) {
-                       pnpacpi_parse_allocated_irqresource(res_table, 
-                               acpi_register_gsi(res->data.irq.interrupts[0],
-                                       res->data.irq.edge_level,
-                                       res->data.irq.active_high_low));
-                       pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 
1);
+               /*
+                * Per spec, only one interrupt per descriptor is allowed in
+                * _CRS, but some firmware violates this, so parse them all.
+                */
+               for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
+                       pnpacpi_parse_allocated_irqresource(res_table,
+                               res->data.irq.interrupts[i],
+                               res->data.irq.edge_level,
+                               res->data.irq.active_high_low);
                }
                break;
 
        case ACPI_RSTYPE_EXT_IRQ:
-               if ((res->data.extended_irq.number_of_interrupts > 0) &&
-                       valid_IRQ(res->data.extended_irq.interrupts[0])) {
-                       pnpacpi_parse_allocated_irqresource(res_table, 
-                               
acpi_register_gsi(res->data.extended_irq.interrupts[0],
-                                       res->data.extended_irq.edge_level,
-                                       
res->data.extended_irq.active_high_low));
-                       
pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1);
+               for (i = 0; i < res->data.extended_irq.number_of_interrupts; 
i++) {
+                       pnpacpi_parse_allocated_irqresource(res_table,
+                               res->data.extended_irq.interrupts[i],
+                               res->data.extended_irq.edge_level,
+                               res->data.extended_irq.active_high_low);
                }
                break;
        case ACPI_RSTYPE_DMA:
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to