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 | |
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>
-rw-r--r-- | arch/ia64/kernel/iosapic.c | 61 | ||||
-rw-r--r-- | arch/ia64/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 201 | ||||
-rw-r--r-- | arch/ia64/kernel/smpboot.c | 4 | ||||
-rw-r--r-- | include/asm-ia64/hw_irq.h | 15 |
5 files changed, 219 insertions, 64 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; |
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 407b45870489..cc3ee4ef37af 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c | |||
@@ -35,7 +35,7 @@ void ack_bad_irq(unsigned int irq) | |||
35 | #ifdef CONFIG_IA64_GENERIC | 35 | #ifdef CONFIG_IA64_GENERIC |
36 | unsigned int __ia64_local_vector_to_irq (ia64_vector vec) | 36 | unsigned int __ia64_local_vector_to_irq (ia64_vector vec) |
37 | { | 37 | { |
38 | return (unsigned int) vec; | 38 | return __get_cpu_var(vector_irq)[vec]; |
39 | } | 39 | } |
40 | #endif | 40 | #endif |
41 | 41 | ||
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index bc47049f060f..072427c2c3f6 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c | |||
@@ -46,6 +46,12 @@ | |||
46 | 46 | ||
47 | #define IRQ_DEBUG 0 | 47 | #define IRQ_DEBUG 0 |
48 | 48 | ||
49 | #define IRQ_VECTOR_UNASSIGNED (0) | ||
50 | |||
51 | #define IRQ_UNUSED (0) | ||
52 | #define IRQ_USED (1) | ||
53 | #define IRQ_RSVD (2) | ||
54 | |||
49 | /* These can be overridden in platform_irq_init */ | 55 | /* These can be overridden in platform_irq_init */ |
50 | int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; | 56 | int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; |
51 | int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; | 57 | int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; |
@@ -64,46 +70,161 @@ __u8 isa_irq_to_vector_map[16] = { | |||
64 | }; | 70 | }; |
65 | EXPORT_SYMBOL(isa_irq_to_vector_map); | 71 | EXPORT_SYMBOL(isa_irq_to_vector_map); |
66 | 72 | ||
67 | static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; | 73 | DEFINE_SPINLOCK(vector_lock); |
74 | |||
75 | struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { | ||
76 | [0 ... NR_IRQS - 1] = { .vector = IRQ_VECTOR_UNASSIGNED } | ||
77 | }; | ||
78 | |||
79 | DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = { | ||
80 | [0 ... IA64_NUM_VECTORS - 1] = IA64_SPURIOUS_INT_VECTOR | ||
81 | }; | ||
82 | |||
83 | static int irq_status[NR_IRQS] = { | ||
84 | [0 ... NR_IRQS -1] = IRQ_UNUSED | ||
85 | }; | ||
86 | |||
87 | int check_irq_used(int irq) | ||
88 | { | ||
89 | if (irq_status[irq] == IRQ_USED) | ||
90 | return 1; | ||
91 | |||
92 | return -1; | ||
93 | } | ||
94 | |||
95 | static void reserve_irq(unsigned int irq) | ||
96 | { | ||
97 | unsigned long flags; | ||
98 | |||
99 | spin_lock_irqsave(&vector_lock, flags); | ||
100 | irq_status[irq] = IRQ_RSVD; | ||
101 | spin_unlock_irqrestore(&vector_lock, flags); | ||
102 | } | ||
103 | |||
104 | static inline int find_unassigned_irq(void) | ||
105 | { | ||
106 | int irq; | ||
107 | |||
108 | for (irq = IA64_FIRST_DEVICE_VECTOR; irq < NR_IRQS; irq++) | ||
109 | if (irq_status[irq] == IRQ_UNUSED) | ||
110 | return irq; | ||
111 | return -ENOSPC; | ||
112 | } | ||
113 | |||
114 | static inline int find_unassigned_vector(void) | ||
115 | { | ||
116 | int vector; | ||
117 | |||
118 | for (vector = IA64_FIRST_DEVICE_VECTOR; | ||
119 | vector <= IA64_LAST_DEVICE_VECTOR; vector++) | ||
120 | if (__get_cpu_var(vector_irq[vector]) == IA64_SPURIOUS_INT_VECTOR) | ||
121 | return vector; | ||
122 | return -ENOSPC; | ||
123 | } | ||
124 | |||
125 | static int __bind_irq_vector(int irq, int vector) | ||
126 | { | ||
127 | int cpu; | ||
128 | |||
129 | if (irq_to_vector(irq) == vector) | ||
130 | return 0; | ||
131 | if (irq_to_vector(irq) != IRQ_VECTOR_UNASSIGNED) | ||
132 | return -EBUSY; | ||
133 | for_each_online_cpu(cpu) | ||
134 | per_cpu(vector_irq, cpu)[vector] = irq; | ||
135 | irq_cfg[irq].vector = vector; | ||
136 | irq_status[irq] = IRQ_USED; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int bind_irq_vector(int irq, int vector) | ||
141 | { | ||
142 | unsigned long flags; | ||
143 | int ret; | ||
144 | |||
145 | spin_lock_irqsave(&vector_lock, flags); | ||
146 | ret = __bind_irq_vector(irq, vector); | ||
147 | spin_unlock_irqrestore(&vector_lock, flags); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static void clear_irq_vector(int irq) | ||
152 | { | ||
153 | unsigned long flags; | ||
154 | int vector, cpu; | ||
155 | |||
156 | spin_lock_irqsave(&vector_lock, flags); | ||
157 | BUG_ON((unsigned)irq >= NR_IRQS); | ||
158 | BUG_ON(irq_cfg[irq].vector == IRQ_VECTOR_UNASSIGNED); | ||
159 | vector = irq_cfg[irq].vector; | ||
160 | for_each_online_cpu(cpu) | ||
161 | per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; | ||
162 | irq_cfg[irq].vector = IRQ_VECTOR_UNASSIGNED; | ||
163 | irq_status[irq] = IRQ_UNUSED; | ||
164 | spin_unlock_irqrestore(&vector_lock, flags); | ||
165 | } | ||
68 | 166 | ||
69 | int | 167 | int |
70 | assign_irq_vector (int irq) | 168 | assign_irq_vector (int irq) |
71 | { | 169 | { |
72 | int pos, vector; | 170 | unsigned long flags; |
73 | again: | 171 | int vector = -ENOSPC; |
74 | pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS); | 172 | |
75 | vector = IA64_FIRST_DEVICE_VECTOR + pos; | 173 | if (irq < 0) { |
76 | if (vector > IA64_LAST_DEVICE_VECTOR) | 174 | goto out; |
77 | return -ENOSPC; | 175 | } |
78 | if (test_and_set_bit(pos, ia64_vector_mask)) | 176 | spin_lock_irqsave(&vector_lock, flags); |
79 | goto again; | 177 | vector = find_unassigned_vector(); |
178 | if (vector < 0) | ||
179 | goto out; | ||
180 | BUG_ON(__bind_irq_vector(irq, vector)); | ||
181 | spin_unlock_irqrestore(&vector_lock, flags); | ||
182 | out: | ||
80 | return vector; | 183 | return vector; |
81 | } | 184 | } |
82 | 185 | ||
83 | void | 186 | void |
84 | free_irq_vector (int vector) | 187 | free_irq_vector (int vector) |
85 | { | 188 | { |
86 | int pos; | 189 | if (vector < IA64_FIRST_DEVICE_VECTOR || |
87 | 190 | vector > IA64_LAST_DEVICE_VECTOR) | |
88 | if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) | ||
89 | return; | 191 | return; |
90 | 192 | clear_irq_vector(vector); | |
91 | pos = vector - IA64_FIRST_DEVICE_VECTOR; | ||
92 | if (!test_and_clear_bit(pos, ia64_vector_mask)) | ||
93 | printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); | ||
94 | } | 193 | } |
95 | 194 | ||
96 | int | 195 | int |
97 | reserve_irq_vector (int vector) | 196 | reserve_irq_vector (int vector) |
98 | { | 197 | { |
99 | int pos; | ||
100 | |||
101 | if (vector < IA64_FIRST_DEVICE_VECTOR || | 198 | if (vector < IA64_FIRST_DEVICE_VECTOR || |
102 | vector > IA64_LAST_DEVICE_VECTOR) | 199 | vector > IA64_LAST_DEVICE_VECTOR) |
103 | return -EINVAL; | 200 | return -EINVAL; |
201 | return !!bind_irq_vector(vector, vector); | ||
202 | } | ||
104 | 203 | ||
105 | pos = vector - IA64_FIRST_DEVICE_VECTOR; | 204 | /* |
106 | return test_and_set_bit(pos, ia64_vector_mask); | 205 | * Initialize vector_irq on a new cpu. This function must be called |
206 | * with vector_lock held. | ||
207 | */ | ||
208 | void __setup_vector_irq(int cpu) | ||
209 | { | ||
210 | int irq, vector; | ||
211 | |||
212 | /* Clear vector_irq */ | ||
213 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) | ||
214 | per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR; | ||
215 | /* Mark the inuse vectors */ | ||
216 | for (irq = 0; irq < NR_IRQS; ++irq) { | ||
217 | if ((vector = irq_to_vector(irq)) != IRQ_VECTOR_UNASSIGNED) | ||
218 | per_cpu(vector_irq, cpu)[vector] = irq; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | void destroy_and_reserve_irq(unsigned int irq) | ||
223 | { | ||
224 | dynamic_irq_cleanup(irq); | ||
225 | |||
226 | clear_irq_vector(irq); | ||
227 | reserve_irq(irq); | ||
107 | } | 228 | } |
108 | 229 | ||
109 | /* | 230 | /* |
@@ -111,18 +232,29 @@ reserve_irq_vector (int vector) | |||
111 | */ | 232 | */ |
112 | int create_irq(void) | 233 | int create_irq(void) |
113 | { | 234 | { |
114 | int vector = assign_irq_vector(AUTO_ASSIGN); | 235 | unsigned long flags; |
115 | 236 | int irq, vector; | |
116 | if (vector >= 0) | 237 | |
117 | dynamic_irq_init(vector); | 238 | irq = -ENOSPC; |
118 | 239 | spin_lock_irqsave(&vector_lock, flags); | |
119 | return vector; | 240 | vector = find_unassigned_vector(); |
241 | if (vector < 0) | ||
242 | goto out; | ||
243 | irq = find_unassigned_irq(); | ||
244 | if (irq < 0) | ||
245 | goto out; | ||
246 | BUG_ON(__bind_irq_vector(irq, vector)); | ||
247 | out: | ||
248 | spin_unlock_irqrestore(&vector_lock, flags); | ||
249 | if (irq >= 0) | ||
250 | dynamic_irq_init(irq); | ||
251 | return irq; | ||
120 | } | 252 | } |
121 | 253 | ||
122 | void destroy_irq(unsigned int irq) | 254 | void destroy_irq(unsigned int irq) |
123 | { | 255 | { |
124 | dynamic_irq_cleanup(irq); | 256 | dynamic_irq_cleanup(irq); |
125 | free_irq_vector(irq); | 257 | clear_irq_vector(irq); |
126 | } | 258 | } |
127 | 259 | ||
128 | #ifdef CONFIG_SMP | 260 | #ifdef CONFIG_SMP |
@@ -301,14 +433,13 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action) | |||
301 | irq_desc_t *desc; | 433 | irq_desc_t *desc; |
302 | unsigned int irq; | 434 | unsigned int irq; |
303 | 435 | ||
304 | for (irq = 0; irq < NR_IRQS; ++irq) | 436 | irq = vec; |
305 | if (irq_to_vector(irq) == vec) { | 437 | BUG_ON(bind_irq_vector(irq, vec)); |
306 | desc = irq_desc + irq; | 438 | desc = irq_desc + irq; |
307 | desc->status |= IRQ_PER_CPU; | 439 | desc->status |= IRQ_PER_CPU; |
308 | desc->chip = &irq_type_ia64_lsapic; | 440 | desc->chip = &irq_type_ia64_lsapic; |
309 | if (action) | 441 | if (action) |
310 | setup_irq(irq, action); | 442 | setup_irq(irq, action); |
311 | } | ||
312 | } | 443 | } |
313 | 444 | ||
314 | void __init | 445 | void __init |
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 3c9d8e6089cf..9f5c90b594b9 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -395,9 +395,13 @@ smp_callin (void) | |||
395 | fix_b0_for_bsp(); | 395 | fix_b0_for_bsp(); |
396 | 396 | ||
397 | lock_ipi_calllock(); | 397 | lock_ipi_calllock(); |
398 | spin_lock(&vector_lock); | ||
399 | /* Setup the per cpu irq handling data structures */ | ||
400 | __setup_vector_irq(cpuid); | ||
398 | cpu_set(cpuid, cpu_online_map); | 401 | cpu_set(cpuid, cpu_online_map); |
399 | unlock_ipi_calllock(); | 402 | unlock_ipi_calllock(); |
400 | per_cpu(cpu_state, cpuid) = CPU_ONLINE; | 403 | per_cpu(cpu_state, cpuid) = CPU_ONLINE; |
404 | spin_unlock(&vector_lock); | ||
401 | 405 | ||
402 | smp_setup_percpu_timer(); | 406 | smp_setup_percpu_timer(); |
403 | 407 | ||
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index c054d7a9aaa7..4eff7ff2da82 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h | |||
@@ -90,13 +90,24 @@ enum { | |||
90 | extern __u8 isa_irq_to_vector_map[16]; | 90 | extern __u8 isa_irq_to_vector_map[16]; |
91 | #define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)] | 91 | #define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)] |
92 | 92 | ||
93 | struct irq_cfg { | ||
94 | ia64_vector vector; | ||
95 | }; | ||
96 | extern spinlock_t vector_lock; | ||
97 | extern struct irq_cfg irq_cfg[NR_IRQS]; | ||
98 | DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq); | ||
99 | |||
93 | extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ | 100 | extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ |
94 | 101 | ||
102 | extern int bind_irq_vector(int irq, int vector); | ||
95 | extern int assign_irq_vector (int irq); /* allocate a free vector */ | 103 | extern int assign_irq_vector (int irq); /* allocate a free vector */ |
96 | extern void free_irq_vector (int vector); | 104 | extern void free_irq_vector (int vector); |
97 | extern int reserve_irq_vector (int vector); | 105 | extern int reserve_irq_vector (int vector); |
106 | extern void __setup_vector_irq(int cpu); | ||
98 | extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); | 107 | extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); |
99 | extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); | 108 | extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); |
109 | extern int check_irq_used (int irq); | ||
110 | extern void destroy_and_reserve_irq (unsigned int irq); | ||
100 | 111 | ||
101 | static inline void ia64_resend_irq(unsigned int vector) | 112 | static inline void ia64_resend_irq(unsigned int vector) |
102 | { | 113 | { |
@@ -113,7 +124,7 @@ extern irq_desc_t irq_desc[NR_IRQS]; | |||
113 | static inline unsigned int | 124 | static inline unsigned int |
114 | __ia64_local_vector_to_irq (ia64_vector vec) | 125 | __ia64_local_vector_to_irq (ia64_vector vec) |
115 | { | 126 | { |
116 | return (unsigned int) vec; | 127 | return __get_cpu_var(vector_irq)[vec]; |
117 | } | 128 | } |
118 | #endif | 129 | #endif |
119 | 130 | ||
@@ -131,7 +142,7 @@ __ia64_local_vector_to_irq (ia64_vector vec) | |||
131 | static inline ia64_vector | 142 | static inline ia64_vector |
132 | irq_to_vector (int irq) | 143 | irq_to_vector (int irq) |
133 | { | 144 | { |
134 | return (ia64_vector) irq; | 145 | return irq_cfg[irq].vector; |
135 | } | 146 | } |
136 | 147 | ||
137 | /* | 148 | /* |