aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2005-09-03 00:37:56 -0400
committerLen Brown <len.brown@intel.com>2005-09-03 00:42:56 -0400
commitdbed12da5bb06b15c63930e9282b45daea566d7b (patch)
treed5133cd1d506c77659fa0f9781bf67630f342884 /drivers/pnp
parent5f0110f2a716376f3b260703835f527ca8900946 (diff)
[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 <bjorn.helgaas@hp.com> Cc: Adam Belay <ambx1@neo.rr.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 1e296cbef004..6db549c9480c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -73,25 +73,35 @@ static void decode_irq_flags(int flag, int *edge_level, int *active_high_low)
73} 73}
74 74
75static void 75static void
76pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq) 76pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
77 int edge_level, int active_high_low)
77{ 78{
78 int i = 0; 79 int i = 0;
80 int irq;
81
82 if (!valid_IRQ(gsi))
83 return;
84
79 while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && 85 while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
80 i < PNP_MAX_IRQ) 86 i < PNP_MAX_IRQ)
81 i++; 87 i++;
82 if (i < PNP_MAX_IRQ) { 88 if (i >= PNP_MAX_IRQ)
83 res->irq_resource[i].flags = IORESOURCE_IRQ; //Also clears _UNSET flag 89 return;
84 if (irq < 0) { 90
85 res->irq_resource[i].flags |= IORESOURCE_DISABLED; 91 res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
86 return; 92 irq = acpi_register_gsi(gsi, edge_level, active_high_low);
87 } 93 if (irq < 0) {
88 res->irq_resource[i].start =(unsigned long) irq; 94 res->irq_resource[i].flags |= IORESOURCE_DISABLED;
89 res->irq_resource[i].end = (unsigned long) irq; 95 return;
90 } 96 }
97
98 res->irq_resource[i].start = irq;
99 res->irq_resource[i].end = irq;
100 pcibios_penalize_isa_irq(irq, 1);
91} 101}
92 102
93static void 103static void
94pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma) 104pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
95{ 105{
96 int i = 0; 106 int i = 0;
97 while (i < PNP_MAX_DMA && 107 while (i < PNP_MAX_DMA &&
@@ -103,14 +113,14 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
103 res->dma_resource[i].flags |= IORESOURCE_DISABLED; 113 res->dma_resource[i].flags |= IORESOURCE_DISABLED;
104 return; 114 return;
105 } 115 }
106 res->dma_resource[i].start =(unsigned long) dma; 116 res->dma_resource[i].start = dma;
107 res->dma_resource[i].end = (unsigned long) dma; 117 res->dma_resource[i].end = dma;
108 } 118 }
109} 119}
110 120
111static void 121static void
112pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, 122pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
113 int io, int len) 123 u32 io, u32 len)
114{ 124{
115 int i = 0; 125 int i = 0;
116 while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && 126 while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -122,14 +132,14 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
122 res->port_resource[i].flags |= IORESOURCE_DISABLED; 132 res->port_resource[i].flags |= IORESOURCE_DISABLED;
123 return; 133 return;
124 } 134 }
125 res->port_resource[i].start = (unsigned long) io; 135 res->port_resource[i].start = io;
126 res->port_resource[i].end = (unsigned long)(io + len - 1); 136 res->port_resource[i].end = io + len - 1;
127 } 137 }
128} 138}
129 139
130static void 140static void
131pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, 141pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
132 int mem, int len) 142 u64 mem, u64 len)
133{ 143{
134 int i = 0; 144 int i = 0;
135 while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && 145 while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -141,8 +151,8 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
141 res->mem_resource[i].flags |= IORESOURCE_DISABLED; 151 res->mem_resource[i].flags |= IORESOURCE_DISABLED;
142 return; 152 return;
143 } 153 }
144 res->mem_resource[i].start = (unsigned long) mem; 154 res->mem_resource[i].start = mem;
145 res->mem_resource[i].end = (unsigned long)(mem + len - 1); 155 res->mem_resource[i].end = mem + len - 1;
146 } 156 }
147} 157}
148 158
@@ -151,27 +161,28 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
151 void *data) 161 void *data)
152{ 162{
153 struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; 163 struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
164 int i;
154 165
155 switch (res->id) { 166 switch (res->id) {
156 case ACPI_RSTYPE_IRQ: 167 case ACPI_RSTYPE_IRQ:
157 if ((res->data.irq.number_of_interrupts > 0) && 168 /*
158 valid_IRQ(res->data.irq.interrupts[0])) { 169 * Per spec, only one interrupt per descriptor is allowed in
159 pnpacpi_parse_allocated_irqresource(res_table, 170 * _CRS, but some firmware violates this, so parse them all.
160 acpi_register_gsi(res->data.irq.interrupts[0], 171 */
161 res->data.irq.edge_level, 172 for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
162 res->data.irq.active_high_low)); 173 pnpacpi_parse_allocated_irqresource(res_table,
163 pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 1); 174 res->data.irq.interrupts[i],
175 res->data.irq.edge_level,
176 res->data.irq.active_high_low);
164 } 177 }
165 break; 178 break;
166 179
167 case ACPI_RSTYPE_EXT_IRQ: 180 case ACPI_RSTYPE_EXT_IRQ:
168 if ((res->data.extended_irq.number_of_interrupts > 0) && 181 for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) {
169 valid_IRQ(res->data.extended_irq.interrupts[0])) { 182 pnpacpi_parse_allocated_irqresource(res_table,
170 pnpacpi_parse_allocated_irqresource(res_table, 183 res->data.extended_irq.interrupts[i],
171 acpi_register_gsi(res->data.extended_irq.interrupts[0], 184 res->data.extended_irq.edge_level,
172 res->data.extended_irq.edge_level, 185 res->data.extended_irq.active_high_low);
173 res->data.extended_irq.active_high_low));
174 pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1);
175 } 186 }
176 break; 187 break;
177 case ACPI_RSTYPE_DMA: 188 case ACPI_RSTYPE_DMA: