diff options
author | Avi Kivity <avi@redhat.com> | 2008-11-19 06:58:46 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:06 -0400 |
commit | 399ec807ddc38ecccf8c06dbde04531cbdc63e11 (patch) | |
tree | 75a4e3ee9cfffb4ecf7b4608bb592c89f2b62219 | |
parent | 193554750441d91e127dd5066b8aebe0f769101c (diff) |
KVM: Userspace controlled irq routing
Currently KVM has a static routing from GSI numbers to interrupts (namely,
0-15 are mapped 1:1 to both PIC and IOAPIC, and 16:23 are mapped 1:1 to
the IOAPIC). This is insufficient for several reasons:
- HPET requires non 1:1 mapping for the timer interrupt
- MSIs need a new method to assign interrupt numbers and dispatch them
- ACPI APIC mode needs to be able to reassign the PCI LINK interrupts to the
ioapics
This patch implements an interrupt routing table (as a linked list, but this
can be easily changed) and a userspace interface to replace the table. The
routing table is initialized according to the current hardwired mapping.
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 5 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 6 | ||||
-rw-r--r-- | include/linux/kvm.h | 33 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 31 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 168 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 36 |
6 files changed, 275 insertions, 4 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 1477f91617a5..dbf527a57341 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -919,6 +919,11 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
919 | r = kvm_ioapic_init(kvm); | 919 | r = kvm_ioapic_init(kvm); |
920 | if (r) | 920 | if (r) |
921 | goto out; | 921 | goto out; |
922 | r = kvm_setup_default_irq_routing(kvm); | ||
923 | if (r) { | ||
924 | kfree(kvm->arch.vioapic); | ||
925 | goto out; | ||
926 | } | ||
922 | break; | 927 | break; |
923 | case KVM_IRQ_LINE: { | 928 | case KVM_IRQ_LINE: { |
924 | struct kvm_irq_level irq_event; | 929 | struct kvm_irq_level irq_event; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 141a0166e51c..32e3a7ec6ad2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1835,6 +1835,12 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1835 | } | 1835 | } |
1836 | } else | 1836 | } else |
1837 | goto out; | 1837 | goto out; |
1838 | r = kvm_setup_default_irq_routing(kvm); | ||
1839 | if (r) { | ||
1840 | kfree(kvm->arch.vpic); | ||
1841 | kfree(kvm->arch.vioapic); | ||
1842 | goto out; | ||
1843 | } | ||
1838 | break; | 1844 | break; |
1839 | case KVM_CREATE_PIT: | 1845 | case KVM_CREATE_PIT: |
1840 | mutex_lock(&kvm->lock); | 1846 | mutex_lock(&kvm->lock); |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 73f348066866..7a5d73a8d4fa 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -399,6 +399,38 @@ struct kvm_trace_rec { | |||
399 | #if defined(CONFIG_X86) | 399 | #if defined(CONFIG_X86) |
400 | #define KVM_CAP_REINJECT_CONTROL 24 | 400 | #define KVM_CAP_REINJECT_CONTROL 24 |
401 | #endif | 401 | #endif |
402 | #if defined(CONFIG_X86)||defined(CONFIG_IA64) | ||
403 | #define KVM_CAP_IRQ_ROUTING 25 | ||
404 | #endif | ||
405 | |||
406 | #ifdef KVM_CAP_IRQ_ROUTING | ||
407 | |||
408 | struct kvm_irq_routing_irqchip { | ||
409 | __u32 irqchip; | ||
410 | __u32 pin; | ||
411 | }; | ||
412 | |||
413 | /* gsi routing entry types */ | ||
414 | #define KVM_IRQ_ROUTING_IRQCHIP 1 | ||
415 | |||
416 | struct kvm_irq_routing_entry { | ||
417 | __u32 gsi; | ||
418 | __u32 type; | ||
419 | __u32 flags; | ||
420 | __u32 pad; | ||
421 | union { | ||
422 | struct kvm_irq_routing_irqchip irqchip; | ||
423 | __u32 pad[8]; | ||
424 | } u; | ||
425 | }; | ||
426 | |||
427 | struct kvm_irq_routing { | ||
428 | __u32 nr; | ||
429 | __u32 flags; | ||
430 | struct kvm_irq_routing_entry entries[0]; | ||
431 | }; | ||
432 | |||
433 | #endif | ||
402 | 434 | ||
403 | /* | 435 | /* |
404 | * ioctls for VM fds | 436 | * ioctls for VM fds |
@@ -430,6 +462,7 @@ struct kvm_trace_rec { | |||
430 | _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone) | 462 | _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone) |
431 | #define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \ | 463 | #define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \ |
432 | struct kvm_assigned_pci_dev) | 464 | struct kvm_assigned_pci_dev) |
465 | #define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing) | ||
433 | #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ | 466 | #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ |
434 | struct kvm_assigned_irq) | 467 | struct kvm_assigned_irq) |
435 | #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) | 468 | #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 99963f36a6db..ce285e01bd57 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -107,6 +107,19 @@ struct kvm_memory_slot { | |||
107 | int user_alloc; | 107 | int user_alloc; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct kvm_kernel_irq_routing_entry { | ||
111 | u32 gsi; | ||
112 | void (*set)(struct kvm_kernel_irq_routing_entry *e, | ||
113 | struct kvm *kvm, int level); | ||
114 | union { | ||
115 | struct { | ||
116 | unsigned irqchip; | ||
117 | unsigned pin; | ||
118 | } irqchip; | ||
119 | }; | ||
120 | struct list_head link; | ||
121 | }; | ||
122 | |||
110 | struct kvm { | 123 | struct kvm { |
111 | struct mutex lock; /* protects the vcpus array and APIC accesses */ | 124 | struct mutex lock; /* protects the vcpus array and APIC accesses */ |
112 | spinlock_t mmu_lock; | 125 | spinlock_t mmu_lock; |
@@ -128,6 +141,7 @@ struct kvm { | |||
128 | #endif | 141 | #endif |
129 | 142 | ||
130 | #ifdef CONFIG_HAVE_KVM_IRQCHIP | 143 | #ifdef CONFIG_HAVE_KVM_IRQCHIP |
144 | struct list_head irq_routing; /* of kvm_kernel_irq_routing_entry */ | ||
131 | struct hlist_head mask_notifier_list; | 145 | struct hlist_head mask_notifier_list; |
132 | #endif | 146 | #endif |
133 | 147 | ||
@@ -480,4 +494,21 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se | |||
480 | } | 494 | } |
481 | #endif | 495 | #endif |
482 | 496 | ||
497 | #ifdef CONFIG_HAVE_KVM_IRQCHIP | ||
498 | |||
499 | #define KVM_MAX_IRQ_ROUTES 1024 | ||
500 | |||
501 | int kvm_setup_default_irq_routing(struct kvm *kvm); | ||
502 | int kvm_set_irq_routing(struct kvm *kvm, | ||
503 | const struct kvm_irq_routing_entry *entries, | ||
504 | unsigned nr, | ||
505 | unsigned flags); | ||
506 | void kvm_free_irq_routing(struct kvm *kvm); | ||
507 | |||
508 | #else | ||
509 | |||
510 | static inline void kvm_free_irq_routing(struct kvm *kvm) {} | ||
511 | |||
512 | #endif | ||
513 | |||
483 | #endif | 514 | #endif |
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 5162a411e4d2..a797fa5e6420 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -24,9 +24,24 @@ | |||
24 | 24 | ||
25 | #include "ioapic.h" | 25 | #include "ioapic.h" |
26 | 26 | ||
27 | static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, | ||
28 | struct kvm *kvm, int level) | ||
29 | { | ||
30 | #ifdef CONFIG_X86 | ||
31 | kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); | ||
32 | #endif | ||
33 | } | ||
34 | |||
35 | static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | ||
36 | struct kvm *kvm, int level) | ||
37 | { | ||
38 | kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); | ||
39 | } | ||
40 | |||
27 | /* This should be called with the kvm->lock mutex held */ | 41 | /* This should be called with the kvm->lock mutex held */ |
28 | void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) | 42 | void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) |
29 | { | 43 | { |
44 | struct kvm_kernel_irq_routing_entry *e; | ||
30 | unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; | 45 | unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; |
31 | 46 | ||
32 | /* Logical OR for level trig interrupt */ | 47 | /* Logical OR for level trig interrupt */ |
@@ -39,10 +54,9 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) | |||
39 | * IOAPIC. So set the bit in both. The guest will ignore | 54 | * IOAPIC. So set the bit in both. The guest will ignore |
40 | * writes to the unused one. | 55 | * writes to the unused one. |
41 | */ | 56 | */ |
42 | kvm_ioapic_set_irq(kvm->arch.vioapic, irq, !!(*irq_state)); | 57 | list_for_each_entry(e, &kvm->irq_routing, link) |
43 | #ifdef CONFIG_X86 | 58 | if (e->gsi == irq) |
44 | kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state)); | 59 | e->set(e, kvm, !!(*irq_state)); |
45 | #endif | ||
46 | } | 60 | } |
47 | 61 | ||
48 | void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi) | 62 | void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi) |
@@ -123,3 +137,149 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) | |||
123 | kimn->func(kimn, mask); | 137 | kimn->func(kimn, mask); |
124 | } | 138 | } |
125 | 139 | ||
140 | static void __kvm_free_irq_routing(struct list_head *irq_routing) | ||
141 | { | ||
142 | struct kvm_kernel_irq_routing_entry *e, *n; | ||
143 | |||
144 | list_for_each_entry_safe(e, n, irq_routing, link) | ||
145 | kfree(e); | ||
146 | } | ||
147 | |||
148 | void kvm_free_irq_routing(struct kvm *kvm) | ||
149 | { | ||
150 | __kvm_free_irq_routing(&kvm->irq_routing); | ||
151 | } | ||
152 | |||
153 | int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, | ||
154 | const struct kvm_irq_routing_entry *ue) | ||
155 | { | ||
156 | int r = -EINVAL; | ||
157 | int delta; | ||
158 | |||
159 | e->gsi = ue->gsi; | ||
160 | switch (ue->type) { | ||
161 | case KVM_IRQ_ROUTING_IRQCHIP: | ||
162 | delta = 0; | ||
163 | switch (ue->u.irqchip.irqchip) { | ||
164 | case KVM_IRQCHIP_PIC_MASTER: | ||
165 | e->set = kvm_set_pic_irq; | ||
166 | break; | ||
167 | case KVM_IRQCHIP_PIC_SLAVE: | ||
168 | e->set = kvm_set_pic_irq; | ||
169 | delta = 8; | ||
170 | break; | ||
171 | case KVM_IRQCHIP_IOAPIC: | ||
172 | e->set = kvm_set_ioapic_irq; | ||
173 | break; | ||
174 | default: | ||
175 | goto out; | ||
176 | } | ||
177 | e->irqchip.irqchip = ue->u.irqchip.irqchip; | ||
178 | e->irqchip.pin = ue->u.irqchip.pin + delta; | ||
179 | break; | ||
180 | default: | ||
181 | goto out; | ||
182 | } | ||
183 | r = 0; | ||
184 | out: | ||
185 | return r; | ||
186 | } | ||
187 | |||
188 | |||
189 | int kvm_set_irq_routing(struct kvm *kvm, | ||
190 | const struct kvm_irq_routing_entry *ue, | ||
191 | unsigned nr, | ||
192 | unsigned flags) | ||
193 | { | ||
194 | struct list_head irq_list = LIST_HEAD_INIT(irq_list); | ||
195 | struct list_head tmp = LIST_HEAD_INIT(tmp); | ||
196 | struct kvm_kernel_irq_routing_entry *e = NULL; | ||
197 | unsigned i; | ||
198 | int r; | ||
199 | |||
200 | for (i = 0; i < nr; ++i) { | ||
201 | r = -EINVAL; | ||
202 | if (ue->gsi >= KVM_MAX_IRQ_ROUTES) | ||
203 | goto out; | ||
204 | if (ue->flags) | ||
205 | goto out; | ||
206 | r = -ENOMEM; | ||
207 | e = kzalloc(sizeof(*e), GFP_KERNEL); | ||
208 | if (!e) | ||
209 | goto out; | ||
210 | r = setup_routing_entry(e, ue); | ||
211 | if (r) | ||
212 | goto out; | ||
213 | ++ue; | ||
214 | list_add(&e->link, &irq_list); | ||
215 | e = NULL; | ||
216 | } | ||
217 | |||
218 | mutex_lock(&kvm->lock); | ||
219 | list_splice(&kvm->irq_routing, &tmp); | ||
220 | INIT_LIST_HEAD(&kvm->irq_routing); | ||
221 | list_splice(&irq_list, &kvm->irq_routing); | ||
222 | INIT_LIST_HEAD(&irq_list); | ||
223 | list_splice(&tmp, &irq_list); | ||
224 | mutex_unlock(&kvm->lock); | ||
225 | |||
226 | r = 0; | ||
227 | |||
228 | out: | ||
229 | kfree(e); | ||
230 | __kvm_free_irq_routing(&irq_list); | ||
231 | return r; | ||
232 | } | ||
233 | |||
234 | #define IOAPIC_ROUTING_ENTRY(irq) \ | ||
235 | { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ | ||
236 | .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) } | ||
237 | #define ROUTING_ENTRY1(irq) IOAPIC_ROUTING_ENTRY(irq) | ||
238 | |||
239 | #ifdef CONFIG_X86 | ||
240 | #define SELECT_PIC(irq) \ | ||
241 | ((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE) | ||
242 | # define PIC_ROUTING_ENTRY(irq) \ | ||
243 | { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ | ||
244 | .u.irqchip.irqchip = SELECT_PIC(irq), .u.irqchip.pin = (irq) % 8 } | ||
245 | # define ROUTING_ENTRY2(irq) \ | ||
246 | IOAPIC_ROUTING_ENTRY(irq), PIC_ROUTING_ENTRY(irq) | ||
247 | #else | ||
248 | # define ROUTING_ENTRY2(irq) \ | ||
249 | IOAPIC_ROUTING_ENTRY(irq) | ||
250 | #endif | ||
251 | |||
252 | static const struct kvm_irq_routing_entry default_routing[] = { | ||
253 | ROUTING_ENTRY2(0), ROUTING_ENTRY2(1), | ||
254 | ROUTING_ENTRY2(2), ROUTING_ENTRY2(3), | ||
255 | ROUTING_ENTRY2(4), ROUTING_ENTRY2(5), | ||
256 | ROUTING_ENTRY2(6), ROUTING_ENTRY2(7), | ||
257 | ROUTING_ENTRY2(8), ROUTING_ENTRY2(9), | ||
258 | ROUTING_ENTRY2(10), ROUTING_ENTRY2(11), | ||
259 | ROUTING_ENTRY2(12), ROUTING_ENTRY2(13), | ||
260 | ROUTING_ENTRY2(14), ROUTING_ENTRY2(15), | ||
261 | ROUTING_ENTRY1(16), ROUTING_ENTRY1(17), | ||
262 | ROUTING_ENTRY1(18), ROUTING_ENTRY1(19), | ||
263 | ROUTING_ENTRY1(20), ROUTING_ENTRY1(21), | ||
264 | ROUTING_ENTRY1(22), ROUTING_ENTRY1(23), | ||
265 | #ifdef CONFIG_IA64 | ||
266 | ROUTING_ENTRY1(24), ROUTING_ENTRY1(25), | ||
267 | ROUTING_ENTRY1(26), ROUTING_ENTRY1(27), | ||
268 | ROUTING_ENTRY1(28), ROUTING_ENTRY1(29), | ||
269 | ROUTING_ENTRY1(30), ROUTING_ENTRY1(31), | ||
270 | ROUTING_ENTRY1(32), ROUTING_ENTRY1(33), | ||
271 | ROUTING_ENTRY1(34), ROUTING_ENTRY1(35), | ||
272 | ROUTING_ENTRY1(36), ROUTING_ENTRY1(37), | ||
273 | ROUTING_ENTRY1(38), ROUTING_ENTRY1(39), | ||
274 | ROUTING_ENTRY1(40), ROUTING_ENTRY1(41), | ||
275 | ROUTING_ENTRY1(42), ROUTING_ENTRY1(43), | ||
276 | ROUTING_ENTRY1(44), ROUTING_ENTRY1(45), | ||
277 | ROUTING_ENTRY1(46), ROUTING_ENTRY1(47), | ||
278 | #endif | ||
279 | }; | ||
280 | |||
281 | int kvm_setup_default_irq_routing(struct kvm *kvm) | ||
282 | { | ||
283 | return kvm_set_irq_routing(kvm, default_routing, | ||
284 | ARRAY_SIZE(default_routing), 0); | ||
285 | } | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 786a3ae373b0..c65484b471c6 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -843,6 +843,7 @@ static struct kvm *kvm_create_vm(void) | |||
843 | if (IS_ERR(kvm)) | 843 | if (IS_ERR(kvm)) |
844 | goto out; | 844 | goto out; |
845 | #ifdef CONFIG_HAVE_KVM_IRQCHIP | 845 | #ifdef CONFIG_HAVE_KVM_IRQCHIP |
846 | INIT_LIST_HEAD(&kvm->irq_routing); | ||
846 | INIT_HLIST_HEAD(&kvm->mask_notifier_list); | 847 | INIT_HLIST_HEAD(&kvm->mask_notifier_list); |
847 | #endif | 848 | #endif |
848 | 849 | ||
@@ -926,6 +927,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
926 | spin_lock(&kvm_lock); | 927 | spin_lock(&kvm_lock); |
927 | list_del(&kvm->vm_list); | 928 | list_del(&kvm->vm_list); |
928 | spin_unlock(&kvm_lock); | 929 | spin_unlock(&kvm_lock); |
930 | kvm_free_irq_routing(kvm); | ||
929 | kvm_io_bus_destroy(&kvm->pio_bus); | 931 | kvm_io_bus_destroy(&kvm->pio_bus); |
930 | kvm_io_bus_destroy(&kvm->mmio_bus); | 932 | kvm_io_bus_destroy(&kvm->mmio_bus); |
931 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 933 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
@@ -1946,6 +1948,36 @@ static long kvm_vm_ioctl(struct file *filp, | |||
1946 | break; | 1948 | break; |
1947 | } | 1949 | } |
1948 | #endif | 1950 | #endif |
1951 | #ifdef KVM_CAP_IRQ_ROUTING | ||
1952 | case KVM_SET_GSI_ROUTING: { | ||
1953 | struct kvm_irq_routing routing; | ||
1954 | struct kvm_irq_routing __user *urouting; | ||
1955 | struct kvm_irq_routing_entry *entries; | ||
1956 | |||
1957 | r = -EFAULT; | ||
1958 | if (copy_from_user(&routing, argp, sizeof(routing))) | ||
1959 | goto out; | ||
1960 | r = -EINVAL; | ||
1961 | if (routing.nr >= KVM_MAX_IRQ_ROUTES) | ||
1962 | goto out; | ||
1963 | if (routing.flags) | ||
1964 | goto out; | ||
1965 | r = -ENOMEM; | ||
1966 | entries = vmalloc(routing.nr * sizeof(*entries)); | ||
1967 | if (!entries) | ||
1968 | goto out; | ||
1969 | r = -EFAULT; | ||
1970 | urouting = argp; | ||
1971 | if (copy_from_user(entries, urouting->entries, | ||
1972 | routing.nr * sizeof(*entries))) | ||
1973 | goto out_free_irq_routing; | ||
1974 | r = kvm_set_irq_routing(kvm, entries, routing.nr, | ||
1975 | routing.flags); | ||
1976 | out_free_irq_routing: | ||
1977 | vfree(entries); | ||
1978 | break; | ||
1979 | } | ||
1980 | #endif | ||
1949 | default: | 1981 | default: |
1950 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); | 1982 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); |
1951 | } | 1983 | } |
@@ -2012,6 +2044,10 @@ static long kvm_dev_ioctl_check_extension_generic(long arg) | |||
2012 | case KVM_CAP_USER_MEMORY: | 2044 | case KVM_CAP_USER_MEMORY: |
2013 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: | 2045 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: |
2014 | return 1; | 2046 | return 1; |
2047 | #ifdef CONFIG_HAVE_KVM_IRQCHIP | ||
2048 | case KVM_CAP_IRQ_ROUTING: | ||
2049 | return 1; | ||
2050 | #endif | ||
2015 | default: | 2051 | default: |
2016 | break; | 2052 | break; |
2017 | } | 2053 | } |