diff options
author | Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> | 2007-07-17 08:22:23 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-07-17 12:51:49 -0400 |
commit | e1b30a392835e92581db09a4e8b4b2ad53a0c370 (patch) | |
tree | 1a0dacd37e682dc4c2222f415f8035057d6bbc30 /arch/ia64/kernel/iosapic.c | |
parent | f8c087f31e1d3fbf1f7d0b3ea5e643f535e7de04 (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.c | 61 |
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 | |||
120 | static struct iosapic { | 123 | static 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 | |||
204 | gsi_to_vector (unsigned int gsi) | 207 | gsi_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; |