aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/pci_link.c')
-rw-r--r--drivers/acpi/pci_link.c103
1 files changed, 87 insertions, 16 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 6ad0e77df9b3..6a29610edc11 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = {
68 }, 68 },
69}; 69};
70 70
71/*
72 * If a link is initialized, we never change its active and initialized
73 * later even the link is disable. Instead, we just repick the active irq
74 */
71struct acpi_pci_link_irq { 75struct acpi_pci_link_irq {
72 u8 active; /* Current IRQ */ 76 u8 active; /* Current IRQ */
73 u8 edge_level; /* All IRQs */ 77 u8 edge_level; /* All IRQs */
@@ -76,8 +80,7 @@ struct acpi_pci_link_irq {
76 u8 possible_count; 80 u8 possible_count;
77 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; 81 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
78 u8 initialized:1; 82 u8 initialized:1;
79 u8 suspend_resume:1; 83 u8 reserved:7;
80 u8 reserved:6;
81}; 84};
82 85
83struct acpi_pci_link { 86struct acpi_pci_link {
@@ -85,12 +88,14 @@ struct acpi_pci_link {
85 struct acpi_device *device; 88 struct acpi_device *device;
86 acpi_handle handle; 89 acpi_handle handle;
87 struct acpi_pci_link_irq irq; 90 struct acpi_pci_link_irq irq;
91 int refcnt;
88}; 92};
89 93
90static struct { 94static struct {
91 int count; 95 int count;
92 struct list_head entries; 96 struct list_head entries;
93} acpi_link; 97} acpi_link;
98DECLARE_MUTEX(acpi_link_lock);
94 99
95 100
96/* -------------------------------------------------------------------------- 101/* --------------------------------------------------------------------------
@@ -532,12 +537,12 @@ static int acpi_pci_link_allocate(
532 537
533 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); 538 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
534 539
535 if (link->irq.suspend_resume) { 540 if (link->irq.initialized) {
536 acpi_pci_link_set(link, link->irq.active); 541 if (link->refcnt == 0)
537 link->irq.suspend_resume = 0; 542 /* This means the link is disabled but initialized */
538 } 543 acpi_pci_link_set(link, link->irq.active);
539 if (link->irq.initialized)
540 return_VALUE(0); 544 return_VALUE(0);
545 }
541 546
542 /* 547 /*
543 * search for active IRQ in list of possible IRQs. 548 * search for active IRQ in list of possible IRQs.
@@ -596,13 +601,13 @@ static int acpi_pci_link_allocate(
596} 601}
597 602
598/* 603/*
599 * acpi_pci_link_get_irq 604 * acpi_pci_link_allocate_irq
600 * success: return IRQ >= 0 605 * success: return IRQ >= 0
601 * failure: return -1 606 * failure: return -1
602 */ 607 */
603 608
604int 609int
605acpi_pci_link_get_irq ( 610acpi_pci_link_allocate_irq (
606 acpi_handle handle, 611 acpi_handle handle,
607 int index, 612 int index,
608 int *edge_level, 613 int *edge_level,
@@ -613,7 +618,7 @@ acpi_pci_link_get_irq (
613 struct acpi_device *device = NULL; 618 struct acpi_device *device = NULL;
614 struct acpi_pci_link *link = NULL; 619 struct acpi_pci_link *link = NULL;
615 620
616 ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); 621 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq");
617 622
618 result = acpi_bus_get_device(handle, &device); 623 result = acpi_bus_get_device(handle, &device);
619 if (result) { 624 if (result) {
@@ -633,21 +638,70 @@ acpi_pci_link_get_irq (
633 return_VALUE(-1); 638 return_VALUE(-1);
634 } 639 }
635 640
636 if (acpi_pci_link_allocate(link)) 641 down(&acpi_link_lock);
642 if (acpi_pci_link_allocate(link)) {
643 up(&acpi_link_lock);
637 return_VALUE(-1); 644 return_VALUE(-1);
645 }
638 646
639 if (!link->irq.active) { 647 if (!link->irq.active) {
648 up(&acpi_link_lock);
640 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); 649 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
641 return_VALUE(-1); 650 return_VALUE(-1);
642 } 651 }
652 link->refcnt ++;
653 up(&acpi_link_lock);
643 654
644 if (edge_level) *edge_level = link->irq.edge_level; 655 if (edge_level) *edge_level = link->irq.edge_level;
645 if (active_high_low) *active_high_low = link->irq.active_high_low; 656 if (active_high_low) *active_high_low = link->irq.active_high_low;
646 if (name) *name = acpi_device_bid(link->device); 657 if (name) *name = acpi_device_bid(link->device);
658 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
659 "Link %s is referenced\n", acpi_device_bid(link->device)));
647 return_VALUE(link->irq.active); 660 return_VALUE(link->irq.active);
648} 661}
649 662
663/*
664 * We don't change link's irq information here. After it is reenabled, we
665 * continue use the info
666 */
667int
668acpi_pci_link_free_irq(acpi_handle handle)
669{
670 struct acpi_device *device = NULL;
671 struct acpi_pci_link *link = NULL;
672 acpi_status result;
673
674 ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq");
675
676 result = acpi_bus_get_device(handle, &device);
677 if (result) {
678 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
679 return_VALUE(-1);
680 }
650 681
682 link = (struct acpi_pci_link *) acpi_driver_data(device);
683 if (!link) {
684 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
685 return_VALUE(-1);
686 }
687
688 down(&acpi_link_lock);
689 if (!link->irq.initialized) {
690 up(&acpi_link_lock);
691 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
692 return_VALUE(-1);
693 }
694
695 link->refcnt --;
696 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
697 "Link %s is dereferenced\n", acpi_device_bid(link->device)));
698
699 if (link->refcnt == 0) {
700 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
701 }
702 up(&acpi_link_lock);
703 return_VALUE(link->irq.active);
704}
651/* -------------------------------------------------------------------------- 705/* --------------------------------------------------------------------------
652 Driver Interface 706 Driver Interface
653 -------------------------------------------------------------------------- */ 707 -------------------------------------------------------------------------- */
@@ -677,6 +731,7 @@ acpi_pci_link_add (
677 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); 731 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
678 acpi_driver_data(device) = link; 732 acpi_driver_data(device) = link;
679 733
734 down(&acpi_link_lock);
680 result = acpi_pci_link_get_possible(link); 735 result = acpi_pci_link_get_possible(link);
681 if (result) 736 if (result)
682 goto end; 737 goto end;
@@ -712,6 +767,7 @@ acpi_pci_link_add (
712end: 767end:
713 /* disable all links -- to be activated on use */ 768 /* disable all links -- to be activated on use */
714 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); 769 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
770 up(&acpi_link_lock);
715 771
716 if (result) 772 if (result)
717 kfree(link); 773 kfree(link);
@@ -726,19 +782,32 @@ irqrouter_suspend(
726{ 782{
727 struct list_head *node = NULL; 783 struct list_head *node = NULL;
728 struct acpi_pci_link *link = NULL; 784 struct acpi_pci_link *link = NULL;
785 int ret = 0;
729 786
730 ACPI_FUNCTION_TRACE("irqrouter_suspend"); 787 ACPI_FUNCTION_TRACE("irqrouter_suspend");
731 788
732 list_for_each(node, &acpi_link.entries) { 789 list_for_each(node, &acpi_link.entries) {
733 link = list_entry(node, struct acpi_pci_link, node); 790 link = list_entry(node, struct acpi_pci_link, node);
734 if (!link) { 791 if (!link) {
735 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); 792 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
793 "Invalid link context\n"));
736 continue; 794 continue;
737 } 795 }
738 if (link->irq.active && link->irq.initialized) 796 if (link->irq.initialized && link->refcnt != 0
739 link->irq.suspend_resume = 1; 797 /* We ignore legacy IDE device irq */
798 && link->irq.active != 14 && link->irq.active !=15) {
799 printk(KERN_WARNING PREFIX
800 "%d drivers with interrupt %d neglected to call"
801 " pci_disable_device at .suspend\n",
802 link->refcnt,
803 link->irq.active);
804 printk(KERN_WARNING PREFIX
805 "Fix the driver, or rmmod before suspend\n");
806 link->refcnt = 0;
807 ret = -EINVAL;
808 }
740 } 809 }
741 return_VALUE(0); 810 return_VALUE(ret);
742} 811}
743 812
744 813
@@ -756,8 +825,9 @@ acpi_pci_link_remove (
756 825
757 link = (struct acpi_pci_link *) acpi_driver_data(device); 826 link = (struct acpi_pci_link *) acpi_driver_data(device);
758 827
759 /* TBD: Acquire/release lock */ 828 down(&acpi_link_lock);
760 list_del(&link->node); 829 list_del(&link->node);
830 up(&acpi_link_lock);
761 831
762 kfree(link); 832 kfree(link);
763 833
@@ -849,6 +919,7 @@ int __init acpi_irq_balance_set(char *str)
849__setup("acpi_irq_balance", acpi_irq_balance_set); 919__setup("acpi_irq_balance", acpi_irq_balance_set);
850 920
851 921
922/* FIXME: we will remove this interface after all drivers call pci_disable_device */
852static struct sysdev_class irqrouter_sysdev_class = { 923static struct sysdev_class irqrouter_sysdev_class = {
853 set_kset_name("irqrouter"), 924 set_kset_name("irqrouter"),
854 .suspend = irqrouter_suspend, 925 .suspend = irqrouter_suspend,