aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:57:17 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:07 -0400
commit1f32ca31e7409d37c1b25e5f81840fb184380cdf (patch)
treee587c85b46b04dbbb5987e2a4986ab174f3bd6fa /drivers/pnp/pnpacpi
parentbbe413b4fc7f791248c7ee00ce7b3778491a3700 (diff)
PNP: convert resource options to single linked list
ISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of a device, i.e., the possibilities an OS bus driver has when it assigns I/O port, MMIO, and other resources to the device. PNP used to maintain this "possible resource setting" information in one independent option structure and a list of dependent option structures for each device. Each of these option structures had lists of I/O, memory, IRQ, and DMA resources, for example: dev independent options ind-io0 -> ind-io1 ... ind-mem0 -> ind-mem1 ... ... dependent option set 0 dep0-io0 -> dep0-io1 ... dep0-mem0 -> dep0-mem1 ... ... dependent option set 1 dep1-io0 -> dep1-io1 ... dep1-mem0 -> dep1-mem1 ... ... ... This data structure was designed for ISAPNP, where the OS configures device resource settings by writing directly to configuration registers. The OS can write the registers in arbitrary order much like it writes PCI BARs. However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces that perform device configuration, and it is important to pass the desired settings to those interfaces in the correct order. The OS learns the correct order by using firmware interfaces that return the "current resource settings" and "possible resource settings," but the option structures above doesn't store the ordering information. This patch replaces the independent and dependent lists with a single list of options. For example, a device might have possible resource settings like this: dev options ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ... All the possible settings are in the same list, in the order they come from the firmware "possible resource settings" list. Each entry is tagged with an independent/dependent flag. Dependent entries also have a "set number" and an optional priority value. All dependent entries must be assigned from the same set. For example, the OS can use all the entries from dependent set 0, or all the entries from dependent set 1, but it cannot mix entries from set 0 with entries from set 1. Prior to this patch PNP didn't keep track of the order of this list, and it assigned all independent options first, then all dependent ones. Using the example above, that resulted in a "desired configuration" list like this: ind->io0 -> ind->io1 -> depN-io0 ... instead of the list the firmware expects, which looks like this: ind->io0 -> depN-io0 -> ind-io1 ... Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp/pnpacpi')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c93
1 files changed, 40 insertions, 53 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index e114b3d2b933..c2f59f4d20bc 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -407,7 +407,7 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
407} 407}
408 408
409static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, 409static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
410 struct pnp_option *option, 410 unsigned int option_flags,
411 struct acpi_resource_dma *p) 411 struct acpi_resource_dma *p)
412{ 412{
413 int i; 413 int i;
@@ -420,11 +420,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
420 map |= 1 << p->channels[i]; 420 map |= 1 << p->channels[i];
421 421
422 flags = dma_flags(p->type, p->bus_master, p->transfer); 422 flags = dma_flags(p->type, p->bus_master, p->transfer);
423 pnp_register_dma_resource(dev, option, map, flags); 423 pnp_register_dma_resource(dev, option_flags, map, flags);
424} 424}
425 425
426static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, 426static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
427 struct pnp_option *option, 427 unsigned int option_flags,
428 struct acpi_resource_irq *p) 428 struct acpi_resource_irq *p)
429{ 429{
430 int i; 430 int i;
@@ -440,11 +440,11 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
440 __set_bit(p->interrupts[i], map.bits); 440 __set_bit(p->interrupts[i], map.bits);
441 441
442 flags = irq_flags(p->triggering, p->polarity, p->sharable); 442 flags = irq_flags(p->triggering, p->polarity, p->sharable);
443 pnp_register_irq_resource(dev, option, &map, flags); 443 pnp_register_irq_resource(dev, option_flags, &map, flags);
444} 444}
445 445
446static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, 446static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
447 struct pnp_option *option, 447 unsigned int option_flags,
448 struct acpi_resource_extended_irq *p) 448 struct acpi_resource_extended_irq *p)
449{ 449{
450 int i; 450 int i;
@@ -467,11 +467,11 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
467 } 467 }
468 468
469 flags = irq_flags(p->triggering, p->polarity, p->sharable); 469 flags = irq_flags(p->triggering, p->polarity, p->sharable);
470 pnp_register_irq_resource(dev, option, &map, flags); 470 pnp_register_irq_resource(dev, option_flags, &map, flags);
471} 471}
472 472
473static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, 473static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
474 struct pnp_option *option, 474 unsigned int option_flags,
475 struct acpi_resource_io *io) 475 struct acpi_resource_io *io)
476{ 476{
477 unsigned char flags = 0; 477 unsigned char flags = 0;
@@ -481,23 +481,23 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
481 481
482 if (io->io_decode == ACPI_DECODE_16) 482 if (io->io_decode == ACPI_DECODE_16)
483 flags = IORESOURCE_IO_16BIT_ADDR; 483 flags = IORESOURCE_IO_16BIT_ADDR;
484 pnp_register_port_resource(dev, option, io->minimum, io->maximum, 484 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
485 io->alignment, io->address_length, flags); 485 io->alignment, io->address_length, flags);
486} 486}
487 487
488static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, 488static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
489 struct pnp_option *option, 489 unsigned int option_flags,
490 struct acpi_resource_fixed_io *io) 490 struct acpi_resource_fixed_io *io)
491{ 491{
492 if (io->address_length == 0) 492 if (io->address_length == 0)
493 return; 493 return;
494 494
495 pnp_register_port_resource(dev, option, io->address, io->address, 0, 495 pnp_register_port_resource(dev, option_flags, io->address, io->address,
496 io->address_length, IORESOURCE_IO_FIXED); 496 0, io->address_length, IORESOURCE_IO_FIXED);
497} 497}
498 498
499static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, 499static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
500 struct pnp_option *option, 500 unsigned int option_flags,
501 struct acpi_resource_memory24 *p) 501 struct acpi_resource_memory24 *p)
502{ 502{
503 unsigned char flags = 0; 503 unsigned char flags = 0;
@@ -507,12 +507,12 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
507 507
508 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 508 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
509 flags = IORESOURCE_MEM_WRITEABLE; 509 flags = IORESOURCE_MEM_WRITEABLE;
510 pnp_register_mem_resource(dev, option, p->minimum, p->maximum, 510 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
511 p->alignment, p->address_length, flags); 511 p->alignment, p->address_length, flags);
512} 512}
513 513
514static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, 514static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
515 struct pnp_option *option, 515 unsigned int option_flags,
516 struct acpi_resource_memory32 *p) 516 struct acpi_resource_memory32 *p)
517{ 517{
518 unsigned char flags = 0; 518 unsigned char flags = 0;
@@ -522,12 +522,12 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
522 522
523 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 523 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
524 flags = IORESOURCE_MEM_WRITEABLE; 524 flags = IORESOURCE_MEM_WRITEABLE;
525 pnp_register_mem_resource(dev, option, p->minimum, p->maximum, 525 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
526 p->alignment, p->address_length, flags); 526 p->alignment, p->address_length, flags);
527} 527}
528 528
529static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, 529static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
530 struct pnp_option *option, 530 unsigned int option_flags,
531 struct acpi_resource_fixed_memory32 *p) 531 struct acpi_resource_fixed_memory32 *p)
532{ 532{
533 unsigned char flags = 0; 533 unsigned char flags = 0;
@@ -537,12 +537,12 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
537 537
538 if (p->write_protect == ACPI_READ_WRITE_MEMORY) 538 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
539 flags = IORESOURCE_MEM_WRITEABLE; 539 flags = IORESOURCE_MEM_WRITEABLE;
540 pnp_register_mem_resource(dev, option, p->address, p->address, 540 pnp_register_mem_resource(dev, option_flags, p->address, p->address,
541 0, p->address_length, flags); 541 0, p->address_length, flags);
542} 542}
543 543
544static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, 544static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
545 struct pnp_option *option, 545 unsigned int option_flags,
546 struct acpi_resource *r) 546 struct acpi_resource *r)
547{ 547{
548 struct acpi_resource_address64 addr, *p = &addr; 548 struct acpi_resource_address64 addr, *p = &addr;
@@ -562,18 +562,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
562 if (p->resource_type == ACPI_MEMORY_RANGE) { 562 if (p->resource_type == ACPI_MEMORY_RANGE) {
563 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) 563 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
564 flags = IORESOURCE_MEM_WRITEABLE; 564 flags = IORESOURCE_MEM_WRITEABLE;
565 pnp_register_mem_resource(dev, option, p->minimum, p->minimum, 565 pnp_register_mem_resource(dev, option_flags, p->minimum,
566 0, p->address_length, flags); 566 p->minimum, 0, p->address_length,
567 flags);
567 } else if (p->resource_type == ACPI_IO_RANGE) 568 } else if (p->resource_type == ACPI_IO_RANGE)
568 pnp_register_port_resource(dev, option, p->minimum, p->minimum, 569 pnp_register_port_resource(dev, option_flags, p->minimum,
569 0, p->address_length, 570 p->minimum, 0, p->address_length,
570 IORESOURCE_IO_FIXED); 571 IORESOURCE_IO_FIXED);
571} 572}
572 573
573struct acpipnp_parse_option_s { 574struct acpipnp_parse_option_s {
574 struct pnp_option *option;
575 struct pnp_option *option_independent;
576 struct pnp_dev *dev; 575 struct pnp_dev *dev;
576 unsigned int option_flags;
577}; 577};
578 578
579static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, 579static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
@@ -582,15 +582,15 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
582 int priority; 582 int priority;
583 struct acpipnp_parse_option_s *parse_data = data; 583 struct acpipnp_parse_option_s *parse_data = data;
584 struct pnp_dev *dev = parse_data->dev; 584 struct pnp_dev *dev = parse_data->dev;
585 struct pnp_option *option = parse_data->option; 585 unsigned int option_flags = parse_data->option_flags;
586 586
587 switch (res->type) { 587 switch (res->type) {
588 case ACPI_RESOURCE_TYPE_IRQ: 588 case ACPI_RESOURCE_TYPE_IRQ:
589 pnpacpi_parse_irq_option(dev, option, &res->data.irq); 589 pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
590 break; 590 break;
591 591
592 case ACPI_RESOURCE_TYPE_DMA: 592 case ACPI_RESOURCE_TYPE_DMA:
593 pnpacpi_parse_dma_option(dev, option, &res->data.dma); 593 pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
594 break; 594 break;
595 595
596 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 596 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -610,31 +610,19 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
610 priority = PNP_RES_PRIORITY_INVALID; 610 priority = PNP_RES_PRIORITY_INVALID;
611 break; 611 break;
612 } 612 }
613 /* TBD: Consider performance/robustness bits */ 613 parse_data->option_flags = pnp_new_dependent_set(dev, priority);
614 option = pnp_register_dependent_option(dev, priority);
615 if (!option)
616 return AE_ERROR;
617 parse_data->option = option;
618 break; 614 break;
619 615
620 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 616 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
621 /*only one EndDependentFn is allowed */ 617 parse_data->option_flags = 0;
622 if (!parse_data->option_independent) {
623 dev_warn(&dev->dev, "more than one EndDependentFn "
624 "in _PRS\n");
625 return AE_ERROR;
626 }
627 parse_data->option = parse_data->option_independent;
628 parse_data->option_independent = NULL;
629 dev_dbg(&dev->dev, "end dependent options\n");
630 break; 618 break;
631 619
632 case ACPI_RESOURCE_TYPE_IO: 620 case ACPI_RESOURCE_TYPE_IO:
633 pnpacpi_parse_port_option(dev, option, &res->data.io); 621 pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
634 break; 622 break;
635 623
636 case ACPI_RESOURCE_TYPE_FIXED_IO: 624 case ACPI_RESOURCE_TYPE_FIXED_IO:
637 pnpacpi_parse_fixed_port_option(dev, option, 625 pnpacpi_parse_fixed_port_option(dev, option_flags,
638 &res->data.fixed_io); 626 &res->data.fixed_io);
639 break; 627 break;
640 628
@@ -643,29 +631,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
643 break; 631 break;
644 632
645 case ACPI_RESOURCE_TYPE_MEMORY24: 633 case ACPI_RESOURCE_TYPE_MEMORY24:
646 pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); 634 pnpacpi_parse_mem24_option(dev, option_flags,
635 &res->data.memory24);
647 break; 636 break;
648 637
649 case ACPI_RESOURCE_TYPE_MEMORY32: 638 case ACPI_RESOURCE_TYPE_MEMORY32:
650 pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); 639 pnpacpi_parse_mem32_option(dev, option_flags,
640 &res->data.memory32);
651 break; 641 break;
652 642
653 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 643 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
654 pnpacpi_parse_fixed_mem32_option(dev, option, 644 pnpacpi_parse_fixed_mem32_option(dev, option_flags,
655 &res->data.fixed_memory32); 645 &res->data.fixed_memory32);
656 break; 646 break;
657 647
658 case ACPI_RESOURCE_TYPE_ADDRESS16: 648 case ACPI_RESOURCE_TYPE_ADDRESS16:
659 case ACPI_RESOURCE_TYPE_ADDRESS32: 649 case ACPI_RESOURCE_TYPE_ADDRESS32:
660 case ACPI_RESOURCE_TYPE_ADDRESS64: 650 case ACPI_RESOURCE_TYPE_ADDRESS64:
661 pnpacpi_parse_address_option(dev, option, res); 651 pnpacpi_parse_address_option(dev, option_flags, res);
662 break; 652 break;
663 653
664 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 654 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
665 break; 655 break;
666 656
667 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 657 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
668 pnpacpi_parse_ext_irq_option(dev, option, 658 pnpacpi_parse_ext_irq_option(dev, option_flags,
669 &res->data.extended_irq); 659 &res->data.extended_irq);
670 break; 660 break;
671 661
@@ -689,12 +679,9 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
689 679
690 dev_dbg(&dev->dev, "parse resource options\n"); 680 dev_dbg(&dev->dev, "parse resource options\n");
691 681
692 parse_data.option = pnp_register_independent_option(dev);
693 if (!parse_data.option)
694 return -ENOMEM;
695
696 parse_data.option_independent = parse_data.option;
697 parse_data.dev = dev; 682 parse_data.dev = dev;
683 parse_data.option_flags = 0;
684
698 status = acpi_walk_resources(handle, METHOD_NAME__PRS, 685 status = acpi_walk_resources(handle, METHOD_NAME__PRS,
699 pnpacpi_option_resource, &parse_data); 686 pnpacpi_option_resource, &parse_data);
700 687