aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/iosapic.c
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>2007-07-17 08:22:23 -0400
committerTony Luck <tony.luck@intel.com>2007-07-17 12:51:49 -0400
commite1b30a392835e92581db09a4e8b4b2ad53a0c370 (patch)
tree1a0dacd37e682dc4c2222f415f8035057d6bbc30 /arch/ia64/kernel/iosapic.c
parentf8c087f31e1d3fbf1f7d0b3ea5e643f535e7de04 (diff)
[IA64] Add mapping table between irq and vector
Add mapping tables between irqs and vectors, and its management code. This is necessary for supporting multiple vector domain because 1:1 mapping between irq and vector will be changed to n:1. The irq == vector relationship between irqs and vectors is explicitly remained for percpu interrupts, platform interrupts, isa IRQs and vectors assigned using assign_irq_vector() because some programs might depend on it. And I should consider the following problem. When pci drivers enabled/disabled devices dynamically, its irq number is changed to the different one. Therefore, suspend/resume code may happen problem. To fix this problem, I bound gsi to irq. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/iosapic.c')
-rw-r--r--arch/ia64/kernel/iosapic.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index cffb443a557c..cf27cfb4d165 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -117,6 +117,9 @@ static DEFINE_SPINLOCK(iosapic_lock);
117 * These tables map IA-64 vectors to the IOSAPIC pin that generates this 117 * These tables map IA-64 vectors to the IOSAPIC pin that generates this
118 * vector. 118 * vector.
119 */ 119 */
120
121#define NO_REF_RTE 0
122
120static struct iosapic { 123static struct iosapic {
121 char __iomem *addr; /* base address of IOSAPIC */ 124 char __iomem *addr; /* base address of IOSAPIC */
122 unsigned int gsi_base; /* GSI base */ 125 unsigned int gsi_base; /* GSI base */
@@ -204,7 +207,7 @@ inline int
204gsi_to_vector (unsigned int gsi) 207gsi_to_vector (unsigned int gsi)
205{ 208{
206 int irq = __gsi_to_irq(gsi); 209 int irq = __gsi_to_irq(gsi);
207 if (irq < 0) 210 if (check_irq_used(irq) < 0)
208 return -1; 211 return -1;
209 return irq_to_vector(irq); 212 return irq_to_vector(irq);
210} 213}
@@ -619,14 +622,18 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
619 iosapic_intr_info[irq].count++; 622 iosapic_intr_info[irq].count++;
620 iosapic_lists[index].rtes_inuse++; 623 iosapic_lists[index].rtes_inuse++;
621 } 624 }
622 else if (irq_is_shared(irq)) { 625 else if (rte->refcnt == NO_REF_RTE) {
623 struct iosapic_intr_info *info = &iosapic_intr_info[irq]; 626 struct iosapic_intr_info *info = &iosapic_intr_info[irq];
624 if (info->trigger != trigger || info->polarity != polarity) { 627 if (info->count > 0 &&
628 (info->trigger != trigger || info->polarity != polarity)){
625 printk (KERN_WARNING 629 printk (KERN_WARNING
626 "%s: cannot override the interrupt\n", 630 "%s: cannot override the interrupt\n",
627 __FUNCTION__); 631 __FUNCTION__);
628 return -EINVAL; 632 return -EINVAL;
629 } 633 }
634 rte->refcnt++;
635 iosapic_intr_info[irq].count++;
636 iosapic_lists[index].rtes_inuse++;
630 } 637 }
631 638
632 iosapic_intr_info[irq].polarity = polarity; 639 iosapic_intr_info[irq].polarity = polarity;
@@ -756,12 +763,17 @@ iosapic_register_intr (unsigned int gsi,
756 irq = __gsi_to_irq(gsi); 763 irq = __gsi_to_irq(gsi);
757 if (irq > 0) { 764 if (irq > 0) {
758 rte = find_rte(irq, gsi); 765 rte = find_rte(irq, gsi);
759 rte->refcnt++; 766 if(iosapic_intr_info[irq].count == 0) {
760 goto unlock_iosapic_lock; 767 assign_irq_vector(irq);
761 } 768 dynamic_irq_init(irq);
769 } else if (rte->refcnt != NO_REF_RTE) {
770 rte->refcnt++;
771 goto unlock_iosapic_lock;
772 }
773 } else
774 irq = create_irq();
762 775
763 /* If vector is running out, we try to find a sharable vector */ 776 /* If vector is running out, we try to find a sharable vector */
764 irq = create_irq();
765 if (irq < 0) { 777 if (irq < 0) {
766 irq = iosapic_find_sharable_irq(trigger, polarity); 778 irq = iosapic_find_sharable_irq(trigger, polarity);
767 if (irq < 0) 779 if (irq < 0)
@@ -832,18 +844,14 @@ iosapic_unregister_intr (unsigned int gsi)
832 if (--rte->refcnt > 0) 844 if (--rte->refcnt > 0)
833 goto out; 845 goto out;
834 846
835 /* Remove the rte entry from the list */
836 idesc = irq_desc + irq; 847 idesc = irq_desc + irq;
837 spin_lock(&idesc->lock); 848 rte->refcnt = NO_REF_RTE;
838 list_del(&rte->rte_list);
839 spin_unlock(&idesc->lock);
840 849
841 /* Mask the interrupt */ 850 /* Mask the interrupt */
842 low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK; 851 low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
843 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); 852 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
844 853
845 iosapic_intr_info[irq].count--; 854 iosapic_intr_info[irq].count--;
846 iosapic_free_rte(rte);
847 index = find_iosapic(gsi); 855 index = find_iosapic(gsi);
848 iosapic_lists[index].rtes_inuse--; 856 iosapic_lists[index].rtes_inuse--;
849 WARN_ON(iosapic_lists[index].rtes_inuse < 0); 857 WARN_ON(iosapic_lists[index].rtes_inuse < 0);
@@ -857,21 +865,20 @@ iosapic_unregister_intr (unsigned int gsi)
857 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), 865 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
858 cpu_logical_id(dest), dest, irq_to_vector(irq)); 866 cpu_logical_id(dest), dest, irq_to_vector(irq));
859 867
860 if (list_empty(&iosapic_intr_info[irq].rtes)) { 868 if (iosapic_intr_info[irq].count == 0) {
861 /* Sanity check */
862 BUG_ON(iosapic_intr_info[irq].count);
863#ifdef CONFIG_SMP 869#ifdef CONFIG_SMP
864 /* Clear affinity */ 870 /* Clear affinity */
865 cpus_setall(idesc->affinity); 871 cpus_setall(idesc->affinity);
866#endif 872#endif
867 /* Clear the interrupt information */ 873 /* Clear the interrupt information */
868 memset(&iosapic_intr_info[irq], 0, 874 iosapic_intr_info[irq].dest = 0;
869 sizeof(struct iosapic_intr_info)); 875 iosapic_intr_info[irq].dmode = 0;
876 iosapic_intr_info[irq].polarity = 0;
877 iosapic_intr_info[irq].trigger = 0;
870 iosapic_intr_info[irq].low32 |= IOSAPIC_MASK; 878 iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
871 INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
872 879
873 /* Destroy IRQ */ 880 /* Destroy and reserve IRQ */
874 destroy_irq(irq); 881 destroy_and_reserve_irq(irq);
875 } 882 }
876 out: 883 out:
877 spin_unlock_irqrestore(&iosapic_lock, flags); 884 spin_unlock_irqrestore(&iosapic_lock, flags);
@@ -892,8 +899,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
892 899
893 switch (int_type) { 900 switch (int_type) {
894 case ACPI_INTERRUPT_PMI: 901 case ACPI_INTERRUPT_PMI:
895 vector = iosapic_vector; 902 irq = vector = iosapic_vector;
896 irq = vector; /* FIXME */ 903 bind_irq_vector(irq, vector);
897 /* 904 /*
898 * since PMI vector is alloc'd by FW(ACPI) not by kernel, 905 * since PMI vector is alloc'd by FW(ACPI) not by kernel,
899 * we need to make sure the vector is available 906 * we need to make sure the vector is available
@@ -909,8 +916,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
909 delivery = IOSAPIC_INIT; 916 delivery = IOSAPIC_INIT;
910 break; 917 break;
911 case ACPI_INTERRUPT_CPEI: 918 case ACPI_INTERRUPT_CPEI:
912 vector = IA64_CPE_VECTOR; 919 irq = vector = IA64_CPE_VECTOR;
913 irq = vector; /* FIXME */ 920 BUG_ON(bind_irq_vector(irq, vector));
914 delivery = IOSAPIC_LOWEST_PRIORITY; 921 delivery = IOSAPIC_LOWEST_PRIORITY;
915 mask = 1; 922 mask = 1;
916 break; 923 break;
@@ -945,8 +952,8 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
945 int vector, irq; 952 int vector, irq;
946 unsigned int dest = cpu_physical_id(smp_processor_id()); 953 unsigned int dest = cpu_physical_id(smp_processor_id());
947 954
948 vector = isa_irq_to_vector(isa_irq); 955 irq = vector = isa_irq_to_vector(isa_irq);
949 irq = vector; /* FIXME */ 956 BUG_ON(bind_irq_vector(irq, vector));
950 register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); 957 register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
951 958
952 DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", 959 DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
@@ -966,6 +973,8 @@ iosapic_system_init (int system_pcat_compat)
966 iosapic_intr_info[irq].low32 = IOSAPIC_MASK; 973 iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
967 /* mark as unused */ 974 /* mark as unused */
968 INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); 975 INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
976
977 iosapic_intr_info[irq].count = 0;
969 } 978 }
970 979
971 pcat_compat = system_pcat_compat; 980 pcat_compat = system_pcat_compat;