aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi/rsparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/pnpacpi/rsparser.c')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c296
1 files changed, 32 insertions, 264 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5be4a392a3ae..b8f4ea7b27fc 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -28,37 +28,6 @@
28#include "../base.h" 28#include "../base.h"
29#include "pnpacpi.h" 29#include "pnpacpi.h"
30 30
31#ifdef CONFIG_IA64
32#define valid_IRQ(i) (1)
33#else
34#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
35#endif
36
37/*
38 * Allocated Resources
39 */
40static int irq_flags(int triggering, int polarity, int shareable)
41{
42 int flags;
43
44 if (triggering == ACPI_LEVEL_SENSITIVE) {
45 if (polarity == ACPI_ACTIVE_LOW)
46 flags = IORESOURCE_IRQ_LOWLEVEL;
47 else
48 flags = IORESOURCE_IRQ_HIGHLEVEL;
49 } else {
50 if (polarity == ACPI_ACTIVE_LOW)
51 flags = IORESOURCE_IRQ_LOWEDGE;
52 else
53 flags = IORESOURCE_IRQ_HIGHEDGE;
54 }
55
56 if (shareable == ACPI_SHARED)
57 flags |= IORESOURCE_IRQ_SHAREABLE;
58
59 return flags;
60}
61
62static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, 31static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
63 int *polarity, int *shareable) 32 int *polarity, int *shareable)
64{ 33{
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
94 *shareable = ACPI_EXCLUSIVE; 63 *shareable = ACPI_EXCLUSIVE;
95} 64}
96 65
97static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
98 u32 gsi, int triggering,
99 int polarity, int shareable)
100{
101 int irq, flags;
102 int p, t;
103
104 if (!valid_IRQ(gsi)) {
105 pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
106 return;
107 }
108
109 /*
110 * in IO-APIC mode, use overrided attribute. Two reasons:
111 * 1. BIOS bug in DSDT
112 * 2. BIOS uses IO-APIC mode Interrupt Source Override
113 */
114 if (!acpi_get_override_irq(gsi, &t, &p)) {
115 t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
116 p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
117
118 if (triggering != t || polarity != p) {
119 dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
120 gsi, t ? "edge":"level", p ? "low":"high");
121 triggering = t;
122 polarity = p;
123 }
124 }
125
126 flags = irq_flags(triggering, polarity, shareable);
127 irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
128 if (irq >= 0)
129 pcibios_penalize_isa_irq(irq, 1);
130 else
131 flags |= IORESOURCE_DISABLED;
132
133 pnp_add_irq_resource(dev, irq, flags);
134}
135
136static int dma_flags(struct pnp_dev *dev, int type, int bus_master, 66static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
137 int transfer) 67 int transfer)
138{ 68{
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
177 return flags; 107 return flags;
178} 108}
179 109
180static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, 110/*
181 u64 len, int io_decode, 111 * Allocated Resources
182 int window) 112 */
183{
184 int flags = 0;
185 u64 end = start + len - 1;
186 113
187 if (io_decode == ACPI_DECODE_16) 114static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
188 flags |= IORESOURCE_IO_16BIT_ADDR; 115{
189 if (len == 0 || end >= 0x10003) 116 if (!(r->flags & IORESOURCE_DISABLED))
190 flags |= IORESOURCE_DISABLED; 117 pcibios_penalize_isa_irq(r->start, 1);
191 if (window)
192 flags |= IORESOURCE_WINDOW;
193 118
194 pnp_add_io_resource(dev, start, end, flags); 119 pnp_add_resource(dev, r);
195} 120}
196 121
197/* 122/*
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
249 } 174 }
250} 175}
251 176
252static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
253 u64 start, u64 len,
254 int write_protect, int window)
255{
256 int flags = 0;
257 u64 end = start + len - 1;
258
259 if (len == 0)
260 flags |= IORESOURCE_DISABLED;
261 if (write_protect == ACPI_READ_WRITE_MEMORY)
262 flags |= IORESOURCE_MEM_WRITEABLE;
263 if (window)
264 flags |= IORESOURCE_WINDOW;
265
266 pnp_add_mem_resource(dev, start, end, flags);
267}
268
269static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
270 u64 start, u64 len)
271{
272 u64 end = start + len - 1;
273
274 pnp_add_bus_resource(dev, start, end);
275}
276
277static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
278 struct acpi_resource *res)
279{
280 struct acpi_resource_address64 addr, *p = &addr;
281 acpi_status status;
282 int window;
283 u64 len;
284
285 status = acpi_resource_to_address64(res, p);
286 if (!ACPI_SUCCESS(status)) {
287 dev_warn(&dev->dev, "failed to convert resource type %d\n",
288 res->type);
289 return;
290 }
291
292 /* Windows apparently computes length rather than using _LEN */
293 len = p->maximum - p->minimum + 1;
294 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
295
296 if (p->resource_type == ACPI_MEMORY_RANGE)
297 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
298 p->info.mem.write_protect, window);
299 else if (p->resource_type == ACPI_IO_RANGE)
300 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
301 p->granularity == 0xfff ? ACPI_DECODE_10 :
302 ACPI_DECODE_16, window);
303 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
304 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
305}
306
307static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
308 struct acpi_resource *res)
309{
310 struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
311 int window;
312 u64 len;
313
314 /* Windows apparently computes length rather than using _LEN */
315 len = p->maximum - p->minimum + 1;
316 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
317
318 if (p->resource_type == ACPI_MEMORY_RANGE)
319 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
320 p->info.mem.write_protect, window);
321 else if (p->resource_type == ACPI_IO_RANGE)
322 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
323 p->granularity == 0xfff ? ACPI_DECODE_10 :
324 ACPI_DECODE_16, window);
325 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
326 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
327}
328
329static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 177static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
330 void *data) 178 void *data)
331{ 179{
332 struct pnp_dev *dev = data; 180 struct pnp_dev *dev = data;
333 struct acpi_resource_irq *irq;
334 struct acpi_resource_dma *dma; 181 struct acpi_resource_dma *dma;
335 struct acpi_resource_io *io;
336 struct acpi_resource_fixed_io *fixed_io;
337 struct acpi_resource_vendor_typed *vendor_typed; 182 struct acpi_resource_vendor_typed *vendor_typed;
338 struct acpi_resource_memory24 *memory24; 183 struct resource r;
339 struct acpi_resource_memory32 *memory32;
340 struct acpi_resource_fixed_memory32 *fixed_memory32;
341 struct acpi_resource_extended_irq *extended_irq;
342 int i, flags; 184 int i, flags;
343 185
344 switch (res->type) { 186 if (acpi_dev_resource_memory(res, &r)
345 case ACPI_RESOURCE_TYPE_IRQ: 187 || acpi_dev_resource_io(res, &r)
346 /* 188 || acpi_dev_resource_address_space(res, &r)
347 * Per spec, only one interrupt per descriptor is allowed in 189 || acpi_dev_resource_ext_address_space(res, &r)) {
348 * _CRS, but some firmware violates this, so parse them all. 190 pnp_add_resource(dev, &r);
349 */ 191 return AE_OK;
350 irq = &res->data.irq; 192 }
351 if (irq->interrupt_count == 0)
352 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
353 else {
354 for (i = 0; i < irq->interrupt_count; i++) {
355 pnpacpi_parse_allocated_irqresource(dev,
356 irq->interrupts[i],
357 irq->triggering,
358 irq->polarity,
359 irq->sharable);
360 }
361 193
194 r.flags = 0;
195 if (acpi_dev_resource_interrupt(res, 0, &r)) {
196 pnpacpi_add_irqresource(dev, &r);
197 for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
198 pnpacpi_add_irqresource(dev, &r);
199
200 if (i > 1) {
362 /* 201 /*
363 * The IRQ encoder puts a single interrupt in each 202 * The IRQ encoder puts a single interrupt in each
364 * descriptor, so if a _CRS descriptor has more than 203 * descriptor, so if a _CRS descriptor has more than
365 * one interrupt, we won't be able to re-encode it. 204 * one interrupt, we won't be able to re-encode it.
366 */ 205 */
367 if (pnp_can_write(dev) && irq->interrupt_count > 1) { 206 if (pnp_can_write(dev)) {
368 dev_warn(&dev->dev, "multiple interrupts in " 207 dev_warn(&dev->dev, "multiple interrupts in "
369 "_CRS descriptor; configuration can't " 208 "_CRS descriptor; configuration can't "
370 "be changed\n"); 209 "be changed\n");
371 dev->capabilities &= ~PNP_WRITE; 210 dev->capabilities &= ~PNP_WRITE;
372 } 211 }
373 } 212 }
374 break; 213 return AE_OK;
214 } else if (r.flags & IORESOURCE_DISABLED) {
215 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
216 return AE_OK;
217 }
375 218
219 switch (res->type) {
376 case ACPI_RESOURCE_TYPE_DMA: 220 case ACPI_RESOURCE_TYPE_DMA:
377 dma = &res->data.dma; 221 dma = &res->data.dma;
378 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) 222 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
383 pnp_add_dma_resource(dev, dma->channels[0], flags); 227 pnp_add_dma_resource(dev, dma->channels[0], flags);
384 break; 228 break;
385 229
386 case ACPI_RESOURCE_TYPE_IO:
387 io = &res->data.io;
388 pnpacpi_parse_allocated_ioresource(dev,
389 io->minimum,
390 io->address_length,
391 io->io_decode, 0);
392 break;
393
394 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 230 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
395 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 231 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
396 break; 232 break;
397 233
398 case ACPI_RESOURCE_TYPE_FIXED_IO:
399 fixed_io = &res->data.fixed_io;
400 pnpacpi_parse_allocated_ioresource(dev,
401 fixed_io->address,
402 fixed_io->address_length,
403 ACPI_DECODE_10, 0);
404 break;
405
406 case ACPI_RESOURCE_TYPE_VENDOR: 234 case ACPI_RESOURCE_TYPE_VENDOR:
407 vendor_typed = &res->data.vendor_typed; 235 vendor_typed = &res->data.vendor_typed;
408 pnpacpi_parse_allocated_vendor(dev, vendor_typed); 236 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
411 case ACPI_RESOURCE_TYPE_END_TAG: 239 case ACPI_RESOURCE_TYPE_END_TAG:
412 break; 240 break;
413 241
414 case ACPI_RESOURCE_TYPE_MEMORY24:
415 memory24 = &res->data.memory24;
416 pnpacpi_parse_allocated_memresource(dev,
417 memory24->minimum,
418 memory24->address_length,
419 memory24->write_protect, 0);
420 break;
421 case ACPI_RESOURCE_TYPE_MEMORY32:
422 memory32 = &res->data.memory32;
423 pnpacpi_parse_allocated_memresource(dev,
424 memory32->minimum,
425 memory32->address_length,
426 memory32->write_protect, 0);
427 break;
428 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
429 fixed_memory32 = &res->data.fixed_memory32;
430 pnpacpi_parse_allocated_memresource(dev,
431 fixed_memory32->address,
432 fixed_memory32->address_length,
433 fixed_memory32->write_protect, 0);
434 break;
435 case ACPI_RESOURCE_TYPE_ADDRESS16:
436 case ACPI_RESOURCE_TYPE_ADDRESS32:
437 case ACPI_RESOURCE_TYPE_ADDRESS64:
438 pnpacpi_parse_allocated_address_space(dev, res);
439 break;
440
441 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
442 pnpacpi_parse_allocated_ext_address_space(dev, res);
443 break;
444
445 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
446 extended_irq = &res->data.extended_irq;
447
448 if (extended_irq->interrupt_count == 0)
449 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
450 else {
451 for (i = 0; i < extended_irq->interrupt_count; i++) {
452 pnpacpi_parse_allocated_irqresource(dev,
453 extended_irq->interrupts[i],
454 extended_irq->triggering,
455 extended_irq->polarity,
456 extended_irq->sharable);
457 }
458
459 /*
460 * The IRQ encoder puts a single interrupt in each
461 * descriptor, so if a _CRS descriptor has more than
462 * one interrupt, we won't be able to re-encode it.
463 */
464 if (pnp_can_write(dev) &&
465 extended_irq->interrupt_count > 1) {
466 dev_warn(&dev->dev, "multiple interrupts in "
467 "_CRS descriptor; configuration can't "
468 "be changed\n");
469 dev->capabilities &= ~PNP_WRITE;
470 }
471 }
472 break;
473
474 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 242 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
475 break; 243 break;
476 244
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
531 if (p->interrupts[i]) 299 if (p->interrupts[i])
532 __set_bit(p->interrupts[i], map.bits); 300 __set_bit(p->interrupts[i], map.bits);
533 301
534 flags = irq_flags(p->triggering, p->polarity, p->sharable); 302 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
535 pnp_register_irq_resource(dev, option_flags, &map, flags); 303 pnp_register_irq_resource(dev, option_flags, &map, flags);
536} 304}
537 305
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
555 } 323 }
556 } 324 }
557 325
558 flags = irq_flags(p->triggering, p->polarity, p->sharable); 326 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
559 pnp_register_irq_resource(dev, option_flags, &map, flags); 327 pnp_register_irq_resource(dev, option_flags, &map, flags);
560} 328}
561 329