aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/isapnp
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/isapnp
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/isapnp')
-rw-r--r--drivers/pnp/isapnp/core.c72
1 files changed, 31 insertions, 41 deletions
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 53cc4d6133e6..101a835e8759 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -429,7 +429,7 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
429 * Add IRQ resource to resources list. 429 * Add IRQ resource to resources list.
430 */ 430 */
431static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, 431static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
432 struct pnp_option *option, 432 unsigned int option_flags,
433 int size) 433 int size)
434{ 434{
435 unsigned char tmp[3]; 435 unsigned char tmp[3];
@@ -446,27 +446,27 @@ static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
446 if (size > 2) 446 if (size > 2)
447 flags = tmp[2]; 447 flags = tmp[2];
448 448
449 pnp_register_irq_resource(dev, option, &map, flags); 449 pnp_register_irq_resource(dev, option_flags, &map, flags);
450} 450}
451 451
452/* 452/*
453 * Add DMA resource to resources list. 453 * Add DMA resource to resources list.
454 */ 454 */
455static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, 455static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
456 struct pnp_option *option, 456 unsigned int option_flags,
457 int size) 457 int size)
458{ 458{
459 unsigned char tmp[2]; 459 unsigned char tmp[2];
460 460
461 isapnp_peek(tmp, size); 461 isapnp_peek(tmp, size);
462 pnp_register_dma_resource(dev, option, tmp[0], tmp[1]); 462 pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]);
463} 463}
464 464
465/* 465/*
466 * Add port resource to resources list. 466 * Add port resource to resources list.
467 */ 467 */
468static void __init isapnp_parse_port_resource(struct pnp_dev *dev, 468static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
469 struct pnp_option *option, 469 unsigned int option_flags,
470 int size) 470 int size)
471{ 471{
472 unsigned char tmp[7]; 472 unsigned char tmp[7];
@@ -479,14 +479,15 @@ static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
479 align = tmp[5]; 479 align = tmp[5];
480 len = tmp[6]; 480 len = tmp[6];
481 flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0; 481 flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
482 pnp_register_port_resource(dev, option, min, max, align, len, flags); 482 pnp_register_port_resource(dev, option_flags,
483 min, max, align, len, flags);
483} 484}
484 485
485/* 486/*
486 * Add fixed port resource to resources list. 487 * Add fixed port resource to resources list.
487 */ 488 */
488static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, 489static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
489 struct pnp_option *option, 490 unsigned int option_flags,
490 int size) 491 int size)
491{ 492{
492 unsigned char tmp[3]; 493 unsigned char tmp[3];
@@ -495,7 +496,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
495 isapnp_peek(tmp, size); 496 isapnp_peek(tmp, size);
496 base = (tmp[1] << 8) | tmp[0]; 497 base = (tmp[1] << 8) | tmp[0];
497 len = tmp[2]; 498 len = tmp[2];
498 pnp_register_port_resource(dev, option, base, base, 0, len, 499 pnp_register_port_resource(dev, option_flags, base, base, 0, len,
499 IORESOURCE_IO_FIXED); 500 IORESOURCE_IO_FIXED);
500} 501}
501 502
@@ -503,7 +504,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
503 * Add memory resource to resources list. 504 * Add memory resource to resources list.
504 */ 505 */
505static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, 506static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
506 struct pnp_option *option, 507 unsigned int option_flags,
507 int size) 508 int size)
508{ 509{
509 unsigned char tmp[9]; 510 unsigned char tmp[9];
@@ -516,14 +517,15 @@ static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
516 align = (tmp[6] << 8) | tmp[5]; 517 align = (tmp[6] << 8) | tmp[5];
517 len = ((tmp[8] << 8) | tmp[7]) << 8; 518 len = ((tmp[8] << 8) | tmp[7]) << 8;
518 flags = tmp[0]; 519 flags = tmp[0];
519 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 520 pnp_register_mem_resource(dev, option_flags,
521 min, max, align, len, flags);
520} 522}
521 523
522/* 524/*
523 * Add 32-bit memory resource to resources list. 525 * Add 32-bit memory resource to resources list.
524 */ 526 */
525static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, 527static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
526 struct pnp_option *option, 528 unsigned int option_flags,
527 int size) 529 int size)
528{ 530{
529 unsigned char tmp[17]; 531 unsigned char tmp[17];
@@ -536,14 +538,15 @@ static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
536 align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; 538 align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
537 len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; 539 len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
538 flags = tmp[0]; 540 flags = tmp[0];
539 pnp_register_mem_resource(dev, option, min, max, align, len, flags); 541 pnp_register_mem_resource(dev, option_flags,
542 min, max, align, len, flags);
540} 543}
541 544
542/* 545/*
543 * Add 32-bit fixed memory resource to resources list. 546 * Add 32-bit fixed memory resource to resources list.
544 */ 547 */
545static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, 548static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
546 struct pnp_option *option, 549 unsigned int option_flags,
547 int size) 550 int size)
548{ 551{
549 unsigned char tmp[9]; 552 unsigned char tmp[9];
@@ -554,7 +557,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
554 base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; 557 base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
555 len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; 558 len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
556 flags = tmp[0]; 559 flags = tmp[0];
557 pnp_register_mem_resource(dev, option, base, base, 0, len, flags); 560 pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
558} 561}
559 562
560/* 563/*
@@ -584,18 +587,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
584{ 587{
585 int number = 0, skip = 0, priority, compat = 0; 588 int number = 0, skip = 0, priority, compat = 0;
586 unsigned char type, tmp[17]; 589 unsigned char type, tmp[17];
587 struct pnp_option *option, *option_independent; 590 unsigned int option_flags;
588 struct pnp_dev *dev; 591 struct pnp_dev *dev;
589 u32 eisa_id; 592 u32 eisa_id;
590 char id[8]; 593 char id[8];
591 594
592 if ((dev = isapnp_parse_device(card, size, number++)) == NULL) 595 if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
593 return 1; 596 return 1;
594 option_independent = option = pnp_register_independent_option(dev); 597 option_flags = 0;
595 if (!option) {
596 kfree(dev);
597 return 1;
598 }
599 pnp_add_card_device(card, dev); 598 pnp_add_card_device(card, dev);
600 599
601 while (1) { 600 while (1) {
@@ -612,12 +611,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
612 return 1; 611 return 1;
613 size = 0; 612 size = 0;
614 skip = 0; 613 skip = 0;
615 option = pnp_register_independent_option(dev); 614 option_flags = 0;
616 option_independent = option;
617 if (!option) {
618 kfree(dev);
619 return 1;
620 }
621 pnp_add_card_device(card, dev); 615 pnp_add_card_device(card, dev);
622 } else { 616 } else {
623 skip = 1; 617 skip = 1;
@@ -638,13 +632,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
638 case _STAG_IRQ: 632 case _STAG_IRQ:
639 if (size < 2 || size > 3) 633 if (size < 2 || size > 3)
640 goto __skip; 634 goto __skip;
641 isapnp_parse_irq_resource(dev, option, size); 635 isapnp_parse_irq_resource(dev, option_flags, size);
642 size = 0; 636 size = 0;
643 break; 637 break;
644 case _STAG_DMA: 638 case _STAG_DMA:
645 if (size != 2) 639 if (size != 2)
646 goto __skip; 640 goto __skip;
647 isapnp_parse_dma_resource(dev, option, size); 641 isapnp_parse_dma_resource(dev, option_flags, size);
648 size = 0; 642 size = 0;
649 break; 643 break;
650 case _STAG_STARTDEP: 644 case _STAG_STARTDEP:
@@ -656,29 +650,24 @@ static int __init isapnp_create_device(struct pnp_card *card,
656 priority = tmp[0]; 650 priority = tmp[0];
657 size = 0; 651 size = 0;
658 } 652 }
659 option = pnp_register_dependent_option(dev, priority); 653 option_flags = pnp_new_dependent_set(dev, priority);
660 if (!option)
661 return 1;
662 break; 654 break;
663 case _STAG_ENDDEP: 655 case _STAG_ENDDEP:
664 if (size != 0) 656 if (size != 0)
665 goto __skip; 657 goto __skip;
666 if (option_independent == option) 658 option_flags = 0;
667 dev_warn(&dev->dev, "missing "
668 "_STAG_STARTDEP tag\n");
669 option = option_independent;
670 dev_dbg(&dev->dev, "end dependent options\n");
671 break; 659 break;
672 case _STAG_IOPORT: 660 case _STAG_IOPORT:
673 if (size != 7) 661 if (size != 7)
674 goto __skip; 662 goto __skip;
675 isapnp_parse_port_resource(dev, option, size); 663 isapnp_parse_port_resource(dev, option_flags, size);
676 size = 0; 664 size = 0;
677 break; 665 break;
678 case _STAG_FIXEDIO: 666 case _STAG_FIXEDIO:
679 if (size != 3) 667 if (size != 3)
680 goto __skip; 668 goto __skip;
681 isapnp_parse_fixed_port_resource(dev, option, size); 669 isapnp_parse_fixed_port_resource(dev, option_flags,
670 size);
682 size = 0; 671 size = 0;
683 break; 672 break;
684 case _STAG_VENDOR: 673 case _STAG_VENDOR:
@@ -686,7 +675,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
686 case _LTAG_MEMRANGE: 675 case _LTAG_MEMRANGE:
687 if (size != 9) 676 if (size != 9)
688 goto __skip; 677 goto __skip;
689 isapnp_parse_mem_resource(dev, option, size); 678 isapnp_parse_mem_resource(dev, option_flags, size);
690 size = 0; 679 size = 0;
691 break; 680 break;
692 case _LTAG_ANSISTR: 681 case _LTAG_ANSISTR:
@@ -701,13 +690,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
701 case _LTAG_MEM32RANGE: 690 case _LTAG_MEM32RANGE:
702 if (size != 17) 691 if (size != 17)
703 goto __skip; 692 goto __skip;
704 isapnp_parse_mem32_resource(dev, option, size); 693 isapnp_parse_mem32_resource(dev, option_flags, size);
705 size = 0; 694 size = 0;
706 break; 695 break;
707 case _LTAG_FIXEDMEM32RANGE: 696 case _LTAG_FIXEDMEM32RANGE:
708 if (size != 9) 697 if (size != 9)
709 goto __skip; 698 goto __skip;
710 isapnp_parse_fixed_mem32_resource(dev, option, size); 699 isapnp_parse_fixed_mem32_resource(dev, option_flags,
700 size);
711 size = 0; 701 size = 0;
712 break; 702 break;
713 case _STAG_END: 703 case _STAG_END: