diff options
Diffstat (limited to 'drivers/acpi/pci_link.c')
-rw-r--r-- | drivers/acpi/pci_link.c | 147 |
1 files changed, 48 insertions, 99 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6c772ca76bd1..16e0f9d3d17c 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -43,13 +43,14 @@ | |||
43 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
44 | #include <acpi/acpi_drivers.h> | 44 | #include <acpi/acpi_drivers.h> |
45 | 45 | ||
46 | #define _COMPONENT ACPI_PCI_COMPONENT | 46 | #define _COMPONENT ACPI_PCI_COMPONENT |
47 | ACPI_MODULE_NAME("pci_link"); | 47 | ACPI_MODULE_NAME("pci_link"); |
48 | #define ACPI_PCI_LINK_CLASS "pci_irq_routing" | 48 | #define ACPI_PCI_LINK_CLASS "pci_irq_routing" |
49 | #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" | 49 | #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" |
50 | #define ACPI_PCI_LINK_FILE_INFO "info" | 50 | #define ACPI_PCI_LINK_FILE_INFO "info" |
51 | #define ACPI_PCI_LINK_FILE_STATUS "state" | 51 | #define ACPI_PCI_LINK_FILE_STATUS "state" |
52 | #define ACPI_PCI_LINK_MAX_POSSIBLE 16 | 52 | #define ACPI_PCI_LINK_MAX_POSSIBLE 16 |
53 | |||
53 | static int acpi_pci_link_add(struct acpi_device *device); | 54 | static int acpi_pci_link_add(struct acpi_device *device); |
54 | static int acpi_pci_link_remove(struct acpi_device *device, int type); | 55 | static int acpi_pci_link_remove(struct acpi_device *device, int type); |
55 | 56 | ||
@@ -66,7 +67,7 @@ static struct acpi_driver acpi_pci_link_driver = { | |||
66 | .ops = { | 67 | .ops = { |
67 | .add = acpi_pci_link_add, | 68 | .add = acpi_pci_link_add, |
68 | .remove = acpi_pci_link_remove, | 69 | .remove = acpi_pci_link_remove, |
69 | }, | 70 | }, |
70 | }; | 71 | }; |
71 | 72 | ||
72 | /* | 73 | /* |
@@ -76,7 +77,7 @@ static struct acpi_driver acpi_pci_link_driver = { | |||
76 | struct acpi_pci_link_irq { | 77 | struct acpi_pci_link_irq { |
77 | u8 active; /* Current IRQ */ | 78 | u8 active; /* Current IRQ */ |
78 | u8 triggering; /* All IRQs */ | 79 | u8 triggering; /* All IRQs */ |
79 | u8 polarity; /* All IRQs */ | 80 | u8 polarity; /* All IRQs */ |
80 | u8 resource_type; | 81 | u8 resource_type; |
81 | u8 possible_count; | 82 | u8 possible_count; |
82 | u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; | 83 | u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; |
@@ -85,16 +86,13 @@ struct acpi_pci_link_irq { | |||
85 | }; | 86 | }; |
86 | 87 | ||
87 | struct acpi_pci_link { | 88 | struct acpi_pci_link { |
88 | struct list_head node; | 89 | struct list_head list; |
89 | struct acpi_device *device; | 90 | struct acpi_device *device; |
90 | struct acpi_pci_link_irq irq; | 91 | struct acpi_pci_link_irq irq; |
91 | int refcnt; | 92 | int refcnt; |
92 | }; | 93 | }; |
93 | 94 | ||
94 | static struct { | 95 | static LIST_HEAD(acpi_link_list); |
95 | int count; | ||
96 | struct list_head entries; | ||
97 | } acpi_link; | ||
98 | static DEFINE_MUTEX(acpi_link_lock); | 96 | static DEFINE_MUTEX(acpi_link_lock); |
99 | 97 | ||
100 | /* -------------------------------------------------------------------------- | 98 | /* -------------------------------------------------------------------------- |
@@ -104,12 +102,11 @@ static DEFINE_MUTEX(acpi_link_lock); | |||
104 | /* | 102 | /* |
105 | * set context (link) possible list from resource list | 103 | * set context (link) possible list from resource list |
106 | */ | 104 | */ |
107 | static acpi_status | 105 | static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource, |
108 | acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) | 106 | void *context) |
109 | { | 107 | { |
110 | struct acpi_pci_link *link = context; | 108 | struct acpi_pci_link *link = context; |
111 | u32 i = 0; | 109 | u32 i; |
112 | |||
113 | 110 | ||
114 | switch (resource->type) { | 111 | switch (resource->type) { |
115 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 112 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -179,10 +176,6 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) | |||
179 | { | 176 | { |
180 | acpi_status status; | 177 | acpi_status status; |
181 | 178 | ||
182 | |||
183 | if (!link) | ||
184 | return -EINVAL; | ||
185 | |||
186 | status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS, | 179 | status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS, |
187 | acpi_pci_link_check_possible, link); | 180 | acpi_pci_link_check_possible, link); |
188 | if (ACPI_FAILURE(status)) { | 181 | if (ACPI_FAILURE(status)) { |
@@ -197,11 +190,10 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) | |||
197 | return 0; | 190 | return 0; |
198 | } | 191 | } |
199 | 192 | ||
200 | static acpi_status | 193 | static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, |
201 | acpi_pci_link_check_current(struct acpi_resource *resource, void *context) | 194 | void *context) |
202 | { | 195 | { |
203 | int *irq = (int *)context; | 196 | int *irq = context; |
204 | |||
205 | 197 | ||
206 | switch (resource->type) { | 198 | switch (resource->type) { |
207 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 199 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -258,12 +250,9 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) | |||
258 | static int acpi_pci_link_get_current(struct acpi_pci_link *link) | 250 | static int acpi_pci_link_get_current(struct acpi_pci_link *link) |
259 | { | 251 | { |
260 | int result = 0; | 252 | int result = 0; |
261 | acpi_status status = AE_OK; | 253 | acpi_status status; |
262 | int irq = 0; | 254 | int irq = 0; |
263 | 255 | ||
264 | if (!link) | ||
265 | return -EINVAL; | ||
266 | |||
267 | link->irq.active = 0; | 256 | link->irq.active = 0; |
268 | 257 | ||
269 | /* in practice, status disabled is meaningless, ignore it */ | 258 | /* in practice, status disabled is meaningless, ignore it */ |
@@ -308,16 +297,15 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link) | |||
308 | 297 | ||
309 | static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) | 298 | static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) |
310 | { | 299 | { |
311 | int result = 0; | 300 | int result; |
312 | acpi_status status = AE_OK; | 301 | acpi_status status; |
313 | struct { | 302 | struct { |
314 | struct acpi_resource res; | 303 | struct acpi_resource res; |
315 | struct acpi_resource end; | 304 | struct acpi_resource end; |
316 | } *resource; | 305 | } *resource; |
317 | struct acpi_buffer buffer = { 0, NULL }; | 306 | struct acpi_buffer buffer = { 0, NULL }; |
318 | 307 | ||
319 | 308 | if (!irq) | |
320 | if (!link || !irq) | ||
321 | return -EINVAL; | 309 | return -EINVAL; |
322 | 310 | ||
323 | resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); | 311 | resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); |
@@ -479,30 +467,22 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { | |||
479 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ | 467 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ |
480 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ | 468 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ |
481 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ | 469 | PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ |
482 | PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ | 470 | PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ |
483 | PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ | 471 | PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ |
484 | PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ | 472 | PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ |
485 | PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ | 473 | PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ |
486 | /* >IRQ15 */ | 474 | /* >IRQ15 */ |
487 | }; | 475 | }; |
488 | 476 | ||
489 | int __init acpi_irq_penalty_init(void) | 477 | int __init acpi_irq_penalty_init(void) |
490 | { | 478 | { |
491 | struct list_head *node = NULL; | 479 | struct acpi_pci_link *link; |
492 | struct acpi_pci_link *link = NULL; | 480 | int i; |
493 | int i = 0; | ||
494 | |||
495 | 481 | ||
496 | /* | 482 | /* |
497 | * Update penalties to facilitate IRQ balancing. | 483 | * Update penalties to facilitate IRQ balancing. |
498 | */ | 484 | */ |
499 | list_for_each(node, &acpi_link.entries) { | 485 | list_for_each_entry(link, &acpi_link_list, list) { |
500 | |||
501 | link = list_entry(node, struct acpi_pci_link, node); | ||
502 | if (!link) { | ||
503 | printk(KERN_ERR PREFIX "Invalid link context\n"); | ||
504 | continue; | ||
505 | } | ||
506 | 486 | ||
507 | /* | 487 | /* |
508 | * reflect the possible and active irqs in the penalty table -- | 488 | * reflect the possible and active irqs in the penalty table -- |
@@ -527,7 +507,6 @@ int __init acpi_irq_penalty_init(void) | |||
527 | } | 507 | } |
528 | /* Add a penalty for the SCI */ | 508 | /* Add a penalty for the SCI */ |
529 | acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; | 509 | acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; |
530 | |||
531 | return 0; | 510 | return 0; |
532 | } | 511 | } |
533 | 512 | ||
@@ -538,7 +517,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
538 | int irq; | 517 | int irq; |
539 | int i; | 518 | int i; |
540 | 519 | ||
541 | |||
542 | if (link->irq.initialized) { | 520 | if (link->irq.initialized) { |
543 | if (link->refcnt == 0) | 521 | if (link->refcnt == 0) |
544 | /* This means the link is disabled but initialized */ | 522 | /* This means the link is disabled but initialized */ |
@@ -566,11 +544,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
566 | /* | 544 | /* |
567 | * if active found, use it; else pick entry from end of possible list. | 545 | * if active found, use it; else pick entry from end of possible list. |
568 | */ | 546 | */ |
569 | if (link->irq.active) { | 547 | if (link->irq.active) |
570 | irq = link->irq.active; | 548 | irq = link->irq.active; |
571 | } else { | 549 | else |
572 | irq = link->irq.possible[link->irq.possible_count - 1]; | 550 | irq = link->irq.possible[link->irq.possible_count - 1]; |
573 | } | ||
574 | 551 | ||
575 | if (acpi_irq_balance || !link->irq.active) { | 552 | if (acpi_irq_balance || !link->irq.active) { |
576 | /* | 553 | /* |
@@ -599,7 +576,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
599 | } | 576 | } |
600 | 577 | ||
601 | link->irq.initialized = 1; | 578 | link->irq.initialized = 1; |
602 | |||
603 | return 0; | 579 | return 0; |
604 | } | 580 | } |
605 | 581 | ||
@@ -608,16 +584,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
608 | * success: return IRQ >= 0 | 584 | * success: return IRQ >= 0 |
609 | * failure: return -1 | 585 | * failure: return -1 |
610 | */ | 586 | */ |
611 | 587 | int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, | |
612 | int | 588 | int *polarity, char **name) |
613 | acpi_pci_link_allocate_irq(acpi_handle handle, | ||
614 | int index, | ||
615 | int *triggering, int *polarity, char **name) | ||
616 | { | 589 | { |
617 | int result = 0; | 590 | int result; |
618 | struct acpi_device *device = NULL; | 591 | struct acpi_device *device; |
619 | struct acpi_pci_link *link = NULL; | 592 | struct acpi_pci_link *link; |
620 | |||
621 | 593 | ||
622 | result = acpi_bus_get_device(handle, &device); | 594 | result = acpi_bus_get_device(handle, &device); |
623 | if (result) { | 595 | if (result) { |
@@ -669,11 +641,10 @@ acpi_pci_link_allocate_irq(acpi_handle handle, | |||
669 | */ | 641 | */ |
670 | int acpi_pci_link_free_irq(acpi_handle handle) | 642 | int acpi_pci_link_free_irq(acpi_handle handle) |
671 | { | 643 | { |
672 | struct acpi_device *device = NULL; | 644 | struct acpi_device *device; |
673 | struct acpi_pci_link *link = NULL; | 645 | struct acpi_pci_link *link; |
674 | acpi_status result; | 646 | acpi_status result; |
675 | 647 | ||
676 | |||
677 | result = acpi_bus_get_device(handle, &device); | 648 | result = acpi_bus_get_device(handle, &device); |
678 | if (result) { | 649 | if (result) { |
679 | printk(KERN_ERR PREFIX "Invalid link device\n"); | 650 | printk(KERN_ERR PREFIX "Invalid link device\n"); |
@@ -708,9 +679,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) | |||
708 | "Link %s is dereferenced\n", | 679 | "Link %s is dereferenced\n", |
709 | acpi_device_bid(link->device))); | 680 | acpi_device_bid(link->device))); |
710 | 681 | ||
711 | if (link->refcnt == 0) { | 682 | if (link->refcnt == 0) |
712 | acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); | 683 | acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); |
713 | } | 684 | |
714 | mutex_unlock(&acpi_link_lock); | 685 | mutex_unlock(&acpi_link_lock); |
715 | return (link->irq.active); | 686 | return (link->irq.active); |
716 | } | 687 | } |
@@ -721,15 +692,11 @@ int acpi_pci_link_free_irq(acpi_handle handle) | |||
721 | 692 | ||
722 | static int acpi_pci_link_add(struct acpi_device *device) | 693 | static int acpi_pci_link_add(struct acpi_device *device) |
723 | { | 694 | { |
724 | int result = 0; | 695 | int result; |
725 | struct acpi_pci_link *link = NULL; | 696 | struct acpi_pci_link *link; |
726 | int i = 0; | 697 | int i; |
727 | int found = 0; | 698 | int found = 0; |
728 | 699 | ||
729 | |||
730 | if (!device) | ||
731 | return -EINVAL; | ||
732 | |||
733 | link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); | 700 | link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); |
734 | if (!link) | 701 | if (!link) |
735 | return -ENOMEM; | 702 | return -ENOMEM; |
@@ -767,9 +734,7 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
767 | 734 | ||
768 | printk("\n"); | 735 | printk("\n"); |
769 | 736 | ||
770 | /* TBD: Acquire/release lock */ | 737 | list_add_tail(&link->list, &acpi_link_list); |
771 | list_add_tail(&link->node, &acpi_link.entries); | ||
772 | acpi_link.count++; | ||
773 | 738 | ||
774 | end: | 739 | end: |
775 | /* disable all links -- to be activated on use */ | 740 | /* disable all links -- to be activated on use */ |
@@ -784,24 +749,17 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
784 | 749 | ||
785 | static int acpi_pci_link_resume(struct acpi_pci_link *link) | 750 | static int acpi_pci_link_resume(struct acpi_pci_link *link) |
786 | { | 751 | { |
787 | |||
788 | if (link->refcnt && link->irq.active && link->irq.initialized) | 752 | if (link->refcnt && link->irq.active && link->irq.initialized) |
789 | return (acpi_pci_link_set(link, link->irq.active)); | 753 | return (acpi_pci_link_set(link, link->irq.active)); |
790 | else | 754 | |
791 | return 0; | 755 | return 0; |
792 | } | 756 | } |
793 | 757 | ||
794 | static int irqrouter_resume(struct sys_device *dev) | 758 | static int irqrouter_resume(struct sys_device *dev) |
795 | { | 759 | { |
796 | struct list_head *node = NULL; | 760 | struct acpi_pci_link *link; |
797 | struct acpi_pci_link *link = NULL; | ||
798 | 761 | ||
799 | list_for_each(node, &acpi_link.entries) { | 762 | list_for_each_entry(link, &acpi_link_list, list) { |
800 | link = list_entry(node, struct acpi_pci_link, node); | ||
801 | if (!link) { | ||
802 | printk(KERN_ERR PREFIX "Invalid link context\n"); | ||
803 | continue; | ||
804 | } | ||
805 | acpi_pci_link_resume(link); | 763 | acpi_pci_link_resume(link); |
806 | } | 764 | } |
807 | return 0; | 765 | return 0; |
@@ -809,20 +767,15 @@ static int irqrouter_resume(struct sys_device *dev) | |||
809 | 767 | ||
810 | static int acpi_pci_link_remove(struct acpi_device *device, int type) | 768 | static int acpi_pci_link_remove(struct acpi_device *device, int type) |
811 | { | 769 | { |
812 | struct acpi_pci_link *link = NULL; | 770 | struct acpi_pci_link *link; |
813 | |||
814 | |||
815 | if (!device || !acpi_driver_data(device)) | ||
816 | return -EINVAL; | ||
817 | 771 | ||
818 | link = acpi_driver_data(device); | 772 | link = acpi_driver_data(device); |
819 | 773 | ||
820 | mutex_lock(&acpi_link_lock); | 774 | mutex_lock(&acpi_link_lock); |
821 | list_del(&link->node); | 775 | list_del(&link->list); |
822 | mutex_unlock(&acpi_link_lock); | 776 | mutex_unlock(&acpi_link_lock); |
823 | 777 | ||
824 | kfree(link); | 778 | kfree(link); |
825 | |||
826 | return 0; | 779 | return 0; |
827 | } | 780 | } |
828 | 781 | ||
@@ -931,7 +884,6 @@ static int __init irqrouter_init_sysfs(void) | |||
931 | { | 884 | { |
932 | int error; | 885 | int error; |
933 | 886 | ||
934 | |||
935 | if (acpi_disabled || acpi_noirq) | 887 | if (acpi_disabled || acpi_noirq) |
936 | return 0; | 888 | return 0; |
937 | 889 | ||
@@ -957,9 +909,6 @@ static int __init acpi_pci_link_init(void) | |||
957 | acpi_irq_balance = 0; | 909 | acpi_irq_balance = 0; |
958 | } | 910 | } |
959 | 911 | ||
960 | acpi_link.count = 0; | ||
961 | INIT_LIST_HEAD(&acpi_link.entries); | ||
962 | |||
963 | if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) | 912 | if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) |
964 | return -ENODEV; | 913 | return -ENODEV; |
965 | 914 | ||