diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/xen/events.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r-- | drivers/xen/events.c | 1042 |
1 files changed, 852 insertions, 190 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 13365ba35218..30df85d8fca8 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * domain gets 1024 event channels, but NR_IRQ is not that large, we | 5 | * domain gets 1024 event channels, but NR_IRQ is not that large, we |
6 | * must dynamically map irqs<->event channels. The event channels | 6 | * must dynamically map irqs<->event channels. The event channels |
7 | * interface with the rest of the kernel by defining a xen interrupt | 7 | * interface with the rest of the kernel by defining a xen interrupt |
8 | * chip. When an event is recieved, it is mapped to an irq and sent | 8 | * chip. When an event is received, it is mapped to an irq and sent |
9 | * through the normal interrupt processing path. | 9 | * through the normal interrupt processing path. |
10 | * | 10 | * |
11 | * There are four kinds of events which can be mapped to an event | 11 | * There are four kinds of events which can be mapped to an event |
@@ -16,7 +16,7 @@ | |||
16 | * (typically dom0). | 16 | * (typically dom0). |
17 | * 2. VIRQs, typically used for timers. These are per-cpu events. | 17 | * 2. VIRQs, typically used for timers. These are per-cpu events. |
18 | * 3. IPIs. | 18 | * 3. IPIs. |
19 | * 4. Hardware interrupts. Not supported at present. | 19 | * 4. PIRQs - Hardware interrupts. |
20 | * | 20 | * |
21 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | 21 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 |
22 | */ | 22 | */ |
@@ -28,12 +28,16 @@ | |||
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/irqnr.h> | ||
32 | #include <linux/pci.h> | ||
31 | 33 | ||
32 | #include <asm/desc.h> | 34 | #include <asm/desc.h> |
33 | #include <asm/ptrace.h> | 35 | #include <asm/ptrace.h> |
34 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
35 | #include <asm/idle.h> | 37 | #include <asm/idle.h> |
38 | #include <asm/io_apic.h> | ||
36 | #include <asm/sync_bitops.h> | 39 | #include <asm/sync_bitops.h> |
40 | #include <asm/xen/pci.h> | ||
37 | #include <asm/xen/hypercall.h> | 41 | #include <asm/xen/hypercall.h> |
38 | #include <asm/xen/hypervisor.h> | 42 | #include <asm/xen/hypervisor.h> |
39 | 43 | ||
@@ -52,6 +56,8 @@ | |||
52 | */ | 56 | */ |
53 | static DEFINE_SPINLOCK(irq_mapping_update_lock); | 57 | static DEFINE_SPINLOCK(irq_mapping_update_lock); |
54 | 58 | ||
59 | static LIST_HEAD(xen_irq_list_head); | ||
60 | |||
55 | /* IRQ <-> VIRQ mapping. */ | 61 | /* IRQ <-> VIRQ mapping. */ |
56 | static DEFINE_PER_CPU(int [NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1}; | 62 | static DEFINE_PER_CPU(int [NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1}; |
57 | 63 | ||
@@ -73,14 +79,17 @@ enum xen_irq_type { | |||
73 | * event channel - irq->event channel mapping | 79 | * event channel - irq->event channel mapping |
74 | * cpu - cpu this event channel is bound to | 80 | * cpu - cpu this event channel is bound to |
75 | * index - type-specific information: | 81 | * index - type-specific information: |
76 | * PIRQ - vector, with MSB being "needs EIO" | 82 | * PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM |
83 | * guest, or GSI (real passthrough IRQ) of the device. | ||
77 | * VIRQ - virq number | 84 | * VIRQ - virq number |
78 | * IPI - IPI vector | 85 | * IPI - IPI vector |
79 | * EVTCHN - | 86 | * EVTCHN - |
80 | */ | 87 | */ |
81 | struct irq_info | 88 | struct irq_info |
82 | { | 89 | { |
90 | struct list_head list; | ||
83 | enum xen_irq_type type; /* type */ | 91 | enum xen_irq_type type; /* type */ |
92 | unsigned irq; | ||
84 | unsigned short evtchn; /* event channel */ | 93 | unsigned short evtchn; /* event channel */ |
85 | unsigned short cpu; /* cpu bound */ | 94 | unsigned short cpu; /* cpu bound */ |
86 | 95 | ||
@@ -88,73 +97,118 @@ struct irq_info | |||
88 | unsigned short virq; | 97 | unsigned short virq; |
89 | enum ipi_vector ipi; | 98 | enum ipi_vector ipi; |
90 | struct { | 99 | struct { |
100 | unsigned short pirq; | ||
91 | unsigned short gsi; | 101 | unsigned short gsi; |
92 | unsigned short vector; | 102 | unsigned char vector; |
103 | unsigned char flags; | ||
104 | uint16_t domid; | ||
93 | } pirq; | 105 | } pirq; |
94 | } u; | 106 | } u; |
95 | }; | 107 | }; |
108 | #define PIRQ_NEEDS_EOI (1 << 0) | ||
109 | #define PIRQ_SHAREABLE (1 << 1) | ||
96 | 110 | ||
97 | static struct irq_info irq_info[NR_IRQS]; | 111 | static int *evtchn_to_irq; |
98 | 112 | ||
99 | static int evtchn_to_irq[NR_EVENT_CHANNELS] = { | 113 | static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], |
100 | [0 ... NR_EVENT_CHANNELS-1] = -1 | 114 | cpu_evtchn_mask); |
101 | }; | ||
102 | struct cpu_evtchn_s { | ||
103 | unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG]; | ||
104 | }; | ||
105 | static struct cpu_evtchn_s *cpu_evtchn_mask_p; | ||
106 | static inline unsigned long *cpu_evtchn_mask(int cpu) | ||
107 | { | ||
108 | return cpu_evtchn_mask_p[cpu].bits; | ||
109 | } | ||
110 | 115 | ||
111 | /* Xen will never allocate port zero for any purpose. */ | 116 | /* Xen will never allocate port zero for any purpose. */ |
112 | #define VALID_EVTCHN(chn) ((chn) != 0) | 117 | #define VALID_EVTCHN(chn) ((chn) != 0) |
113 | 118 | ||
114 | static struct irq_chip xen_dynamic_chip; | 119 | static struct irq_chip xen_dynamic_chip; |
115 | static struct irq_chip xen_percpu_chip; | 120 | static struct irq_chip xen_percpu_chip; |
121 | static struct irq_chip xen_pirq_chip; | ||
122 | static void enable_dynirq(struct irq_data *data); | ||
123 | static void disable_dynirq(struct irq_data *data); | ||
116 | 124 | ||
117 | /* Constructor for packed IRQ information. */ | 125 | /* Get info for IRQ */ |
118 | static struct irq_info mk_unbound_info(void) | 126 | static struct irq_info *info_for_irq(unsigned irq) |
119 | { | 127 | { |
120 | return (struct irq_info) { .type = IRQT_UNBOUND }; | 128 | return irq_get_handler_data(irq); |
121 | } | 129 | } |
122 | 130 | ||
123 | static struct irq_info mk_evtchn_info(unsigned short evtchn) | 131 | /* Constructors for packed IRQ information. */ |
132 | static void xen_irq_info_common_init(struct irq_info *info, | ||
133 | unsigned irq, | ||
134 | enum xen_irq_type type, | ||
135 | unsigned short evtchn, | ||
136 | unsigned short cpu) | ||
124 | { | 137 | { |
125 | return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn, | 138 | |
126 | .cpu = 0 }; | 139 | BUG_ON(info->type != IRQT_UNBOUND && info->type != type); |
140 | |||
141 | info->type = type; | ||
142 | info->irq = irq; | ||
143 | info->evtchn = evtchn; | ||
144 | info->cpu = cpu; | ||
145 | |||
146 | evtchn_to_irq[evtchn] = irq; | ||
127 | } | 147 | } |
128 | 148 | ||
129 | static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi) | 149 | static void xen_irq_info_evtchn_init(unsigned irq, |
150 | unsigned short evtchn) | ||
130 | { | 151 | { |
131 | return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn, | 152 | struct irq_info *info = info_for_irq(irq); |
132 | .cpu = 0, .u.ipi = ipi }; | 153 | |
154 | xen_irq_info_common_init(info, irq, IRQT_EVTCHN, evtchn, 0); | ||
133 | } | 155 | } |
134 | 156 | ||
135 | static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq) | 157 | static void xen_irq_info_ipi_init(unsigned cpu, |
158 | unsigned irq, | ||
159 | unsigned short evtchn, | ||
160 | enum ipi_vector ipi) | ||
136 | { | 161 | { |
137 | return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn, | 162 | struct irq_info *info = info_for_irq(irq); |
138 | .cpu = 0, .u.virq = virq }; | 163 | |
164 | xen_irq_info_common_init(info, irq, IRQT_IPI, evtchn, 0); | ||
165 | |||
166 | info->u.ipi = ipi; | ||
167 | |||
168 | per_cpu(ipi_to_irq, cpu)[ipi] = irq; | ||
139 | } | 169 | } |
140 | 170 | ||
141 | static struct irq_info mk_pirq_info(unsigned short evtchn, | 171 | static void xen_irq_info_virq_init(unsigned cpu, |
142 | unsigned short gsi, unsigned short vector) | 172 | unsigned irq, |
173 | unsigned short evtchn, | ||
174 | unsigned short virq) | ||
143 | { | 175 | { |
144 | return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn, | 176 | struct irq_info *info = info_for_irq(irq); |
145 | .cpu = 0, .u.pirq = { .gsi = gsi, .vector = vector } }; | 177 | |
178 | xen_irq_info_common_init(info, irq, IRQT_VIRQ, evtchn, 0); | ||
179 | |||
180 | info->u.virq = virq; | ||
181 | |||
182 | per_cpu(virq_to_irq, cpu)[virq] = irq; | ||
146 | } | 183 | } |
147 | 184 | ||
148 | /* | 185 | static void xen_irq_info_pirq_init(unsigned irq, |
149 | * Accessors for packed IRQ information. | 186 | unsigned short evtchn, |
150 | */ | 187 | unsigned short pirq, |
151 | static struct irq_info *info_for_irq(unsigned irq) | 188 | unsigned short gsi, |
189 | unsigned short vector, | ||
190 | uint16_t domid, | ||
191 | unsigned char flags) | ||
152 | { | 192 | { |
153 | return &irq_info[irq]; | 193 | struct irq_info *info = info_for_irq(irq); |
194 | |||
195 | xen_irq_info_common_init(info, irq, IRQT_PIRQ, evtchn, 0); | ||
196 | |||
197 | info->u.pirq.pirq = pirq; | ||
198 | info->u.pirq.gsi = gsi; | ||
199 | info->u.pirq.vector = vector; | ||
200 | info->u.pirq.domid = domid; | ||
201 | info->u.pirq.flags = flags; | ||
154 | } | 202 | } |
155 | 203 | ||
204 | /* | ||
205 | * Accessors for packed IRQ information. | ||
206 | */ | ||
156 | static unsigned int evtchn_from_irq(unsigned irq) | 207 | static unsigned int evtchn_from_irq(unsigned irq) |
157 | { | 208 | { |
209 | if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq))) | ||
210 | return 0; | ||
211 | |||
158 | return info_for_irq(irq)->evtchn; | 212 | return info_for_irq(irq)->evtchn; |
159 | } | 213 | } |
160 | 214 | ||
@@ -184,24 +238,14 @@ static unsigned virq_from_irq(unsigned irq) | |||
184 | return info->u.virq; | 238 | return info->u.virq; |
185 | } | 239 | } |
186 | 240 | ||
187 | static unsigned gsi_from_irq(unsigned irq) | 241 | static unsigned pirq_from_irq(unsigned irq) |
188 | { | ||
189 | struct irq_info *info = info_for_irq(irq); | ||
190 | |||
191 | BUG_ON(info == NULL); | ||
192 | BUG_ON(info->type != IRQT_PIRQ); | ||
193 | |||
194 | return info->u.pirq.gsi; | ||
195 | } | ||
196 | |||
197 | static unsigned vector_from_irq(unsigned irq) | ||
198 | { | 242 | { |
199 | struct irq_info *info = info_for_irq(irq); | 243 | struct irq_info *info = info_for_irq(irq); |
200 | 244 | ||
201 | BUG_ON(info == NULL); | 245 | BUG_ON(info == NULL); |
202 | BUG_ON(info->type != IRQT_PIRQ); | 246 | BUG_ON(info->type != IRQT_PIRQ); |
203 | 247 | ||
204 | return info->u.pirq.vector; | 248 | return info->u.pirq.pirq; |
205 | } | 249 | } |
206 | 250 | ||
207 | static enum xen_irq_type type_from_irq(unsigned irq) | 251 | static enum xen_irq_type type_from_irq(unsigned irq) |
@@ -225,12 +269,21 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn) | |||
225 | return ret; | 269 | return ret; |
226 | } | 270 | } |
227 | 271 | ||
272 | static bool pirq_needs_eoi(unsigned irq) | ||
273 | { | ||
274 | struct irq_info *info = info_for_irq(irq); | ||
275 | |||
276 | BUG_ON(info->type != IRQT_PIRQ); | ||
277 | |||
278 | return info->u.pirq.flags & PIRQ_NEEDS_EOI; | ||
279 | } | ||
280 | |||
228 | static inline unsigned long active_evtchns(unsigned int cpu, | 281 | static inline unsigned long active_evtchns(unsigned int cpu, |
229 | struct shared_info *sh, | 282 | struct shared_info *sh, |
230 | unsigned int idx) | 283 | unsigned int idx) |
231 | { | 284 | { |
232 | return (sh->evtchn_pending[idx] & | 285 | return (sh->evtchn_pending[idx] & |
233 | cpu_evtchn_mask(cpu)[idx] & | 286 | per_cpu(cpu_evtchn_mask, cpu)[idx] & |
234 | ~sh->evtchn_mask[idx]); | 287 | ~sh->evtchn_mask[idx]); |
235 | } | 288 | } |
236 | 289 | ||
@@ -240,28 +293,31 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) | |||
240 | 293 | ||
241 | BUG_ON(irq == -1); | 294 | BUG_ON(irq == -1); |
242 | #ifdef CONFIG_SMP | 295 | #ifdef CONFIG_SMP |
243 | cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); | 296 | cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); |
244 | #endif | 297 | #endif |
245 | 298 | ||
246 | __clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); | 299 | clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_from_irq(irq))); |
247 | __set_bit(chn, cpu_evtchn_mask(cpu)); | 300 | set_bit(chn, per_cpu(cpu_evtchn_mask, cpu)); |
248 | 301 | ||
249 | irq_info[irq].cpu = cpu; | 302 | info_for_irq(irq)->cpu = cpu; |
250 | } | 303 | } |
251 | 304 | ||
252 | static void init_evtchn_cpu_bindings(void) | 305 | static void init_evtchn_cpu_bindings(void) |
253 | { | 306 | { |
254 | #ifdef CONFIG_SMP | ||
255 | struct irq_desc *desc; | ||
256 | int i; | 307 | int i; |
308 | #ifdef CONFIG_SMP | ||
309 | struct irq_info *info; | ||
257 | 310 | ||
258 | /* By default all event channels notify CPU#0. */ | 311 | /* By default all event channels notify CPU#0. */ |
259 | for_each_irq_desc(i, desc) { | 312 | list_for_each_entry(info, &xen_irq_list_head, list) { |
260 | cpumask_copy(desc->affinity, cpumask_of(0)); | 313 | struct irq_desc *desc = irq_to_desc(info->irq); |
314 | cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); | ||
261 | } | 315 | } |
262 | #endif | 316 | #endif |
263 | 317 | ||
264 | memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); | 318 | for_each_possible_cpu(i) |
319 | memset(per_cpu(cpu_evtchn_mask, i), | ||
320 | (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i))); | ||
265 | } | 321 | } |
266 | 322 | ||
267 | static inline void clear_evtchn(int port) | 323 | static inline void clear_evtchn(int port) |
@@ -318,7 +374,7 @@ static void unmask_evtchn(int port) | |||
318 | struct evtchn_unmask unmask = { .port = port }; | 374 | struct evtchn_unmask unmask = { .port = port }; |
319 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | 375 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); |
320 | } else { | 376 | } else { |
321 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); | 377 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); |
322 | 378 | ||
323 | sync_clear_bit(port, &s->evtchn_mask[0]); | 379 | sync_clear_bit(port, &s->evtchn_mask[0]); |
324 | 380 | ||
@@ -336,36 +392,417 @@ static void unmask_evtchn(int port) | |||
336 | put_cpu(); | 392 | put_cpu(); |
337 | } | 393 | } |
338 | 394 | ||
339 | static int find_unbound_irq(void) | 395 | static void xen_irq_init(unsigned irq) |
396 | { | ||
397 | struct irq_info *info; | ||
398 | #ifdef CONFIG_SMP | ||
399 | struct irq_desc *desc = irq_to_desc(irq); | ||
400 | |||
401 | /* By default all event channels notify CPU#0. */ | ||
402 | cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); | ||
403 | #endif | ||
404 | |||
405 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
406 | if (info == NULL) | ||
407 | panic("Unable to allocate metadata for IRQ%d\n", irq); | ||
408 | |||
409 | info->type = IRQT_UNBOUND; | ||
410 | |||
411 | irq_set_handler_data(irq, info); | ||
412 | |||
413 | list_add_tail(&info->list, &xen_irq_list_head); | ||
414 | } | ||
415 | |||
416 | static int __must_check xen_allocate_irq_dynamic(void) | ||
340 | { | 417 | { |
418 | int first = 0; | ||
341 | int irq; | 419 | int irq; |
342 | struct irq_desc *desc; | ||
343 | 420 | ||
344 | for (irq = 0; irq < nr_irqs; irq++) { | 421 | #ifdef CONFIG_X86_IO_APIC |
345 | desc = irq_to_desc(irq); | 422 | /* |
346 | /* only 0->15 have init'd desc; handle irq > 16 */ | 423 | * For an HVM guest or domain 0 which see "real" (emulated or |
347 | if (desc == NULL) | 424 | * actual respectively) GSIs we allocate dynamic IRQs |
348 | break; | 425 | * e.g. those corresponding to event channels or MSIs |
349 | if (desc->chip == &no_irq_chip) | 426 | * etc. from the range above those "real" GSIs to avoid |
350 | break; | 427 | * collisions. |
351 | if (desc->chip != &xen_dynamic_chip) | 428 | */ |
429 | if (xen_initial_domain() || xen_hvm_domain()) | ||
430 | first = get_nr_irqs_gsi(); | ||
431 | #endif | ||
432 | |||
433 | irq = irq_alloc_desc_from(first, -1); | ||
434 | |||
435 | xen_irq_init(irq); | ||
436 | |||
437 | return irq; | ||
438 | } | ||
439 | |||
440 | static int __must_check xen_allocate_irq_gsi(unsigned gsi) | ||
441 | { | ||
442 | int irq; | ||
443 | |||
444 | /* | ||
445 | * A PV guest has no concept of a GSI (since it has no ACPI | ||
446 | * nor access to/knowledge of the physical APICs). Therefore | ||
447 | * all IRQs are dynamically allocated from the entire IRQ | ||
448 | * space. | ||
449 | */ | ||
450 | if (xen_pv_domain() && !xen_initial_domain()) | ||
451 | return xen_allocate_irq_dynamic(); | ||
452 | |||
453 | /* Legacy IRQ descriptors are already allocated by the arch. */ | ||
454 | if (gsi < NR_IRQS_LEGACY) | ||
455 | irq = gsi; | ||
456 | else | ||
457 | irq = irq_alloc_desc_at(gsi, -1); | ||
458 | |||
459 | xen_irq_init(irq); | ||
460 | |||
461 | return irq; | ||
462 | } | ||
463 | |||
464 | static void xen_free_irq(unsigned irq) | ||
465 | { | ||
466 | struct irq_info *info = irq_get_handler_data(irq); | ||
467 | |||
468 | list_del(&info->list); | ||
469 | |||
470 | irq_set_handler_data(irq, NULL); | ||
471 | |||
472 | kfree(info); | ||
473 | |||
474 | /* Legacy IRQ descriptors are managed by the arch. */ | ||
475 | if (irq < NR_IRQS_LEGACY) | ||
476 | return; | ||
477 | |||
478 | irq_free_desc(irq); | ||
479 | } | ||
480 | |||
481 | static void pirq_query_unmask(int irq) | ||
482 | { | ||
483 | struct physdev_irq_status_query irq_status; | ||
484 | struct irq_info *info = info_for_irq(irq); | ||
485 | |||
486 | BUG_ON(info->type != IRQT_PIRQ); | ||
487 | |||
488 | irq_status.irq = pirq_from_irq(irq); | ||
489 | if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) | ||
490 | irq_status.flags = 0; | ||
491 | |||
492 | info->u.pirq.flags &= ~PIRQ_NEEDS_EOI; | ||
493 | if (irq_status.flags & XENIRQSTAT_needs_eoi) | ||
494 | info->u.pirq.flags |= PIRQ_NEEDS_EOI; | ||
495 | } | ||
496 | |||
497 | static bool probing_irq(int irq) | ||
498 | { | ||
499 | struct irq_desc *desc = irq_to_desc(irq); | ||
500 | |||
501 | return desc && desc->action == NULL; | ||
502 | } | ||
503 | |||
504 | static void eoi_pirq(struct irq_data *data) | ||
505 | { | ||
506 | int evtchn = evtchn_from_irq(data->irq); | ||
507 | struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) }; | ||
508 | int rc = 0; | ||
509 | |||
510 | irq_move_irq(data); | ||
511 | |||
512 | if (VALID_EVTCHN(evtchn)) | ||
513 | clear_evtchn(evtchn); | ||
514 | |||
515 | if (pirq_needs_eoi(data->irq)) { | ||
516 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); | ||
517 | WARN_ON(rc); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | static void mask_ack_pirq(struct irq_data *data) | ||
522 | { | ||
523 | disable_dynirq(data); | ||
524 | eoi_pirq(data); | ||
525 | } | ||
526 | |||
527 | static unsigned int __startup_pirq(unsigned int irq) | ||
528 | { | ||
529 | struct evtchn_bind_pirq bind_pirq; | ||
530 | struct irq_info *info = info_for_irq(irq); | ||
531 | int evtchn = evtchn_from_irq(irq); | ||
532 | int rc; | ||
533 | |||
534 | BUG_ON(info->type != IRQT_PIRQ); | ||
535 | |||
536 | if (VALID_EVTCHN(evtchn)) | ||
537 | goto out; | ||
538 | |||
539 | bind_pirq.pirq = pirq_from_irq(irq); | ||
540 | /* NB. We are happy to share unless we are probing. */ | ||
541 | bind_pirq.flags = info->u.pirq.flags & PIRQ_SHAREABLE ? | ||
542 | BIND_PIRQ__WILL_SHARE : 0; | ||
543 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); | ||
544 | if (rc != 0) { | ||
545 | if (!probing_irq(irq)) | ||
546 | printk(KERN_INFO "Failed to obtain physical IRQ %d\n", | ||
547 | irq); | ||
548 | return 0; | ||
549 | } | ||
550 | evtchn = bind_pirq.port; | ||
551 | |||
552 | pirq_query_unmask(irq); | ||
553 | |||
554 | evtchn_to_irq[evtchn] = irq; | ||
555 | bind_evtchn_to_cpu(evtchn, 0); | ||
556 | info->evtchn = evtchn; | ||
557 | |||
558 | out: | ||
559 | unmask_evtchn(evtchn); | ||
560 | eoi_pirq(irq_get_irq_data(irq)); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static unsigned int startup_pirq(struct irq_data *data) | ||
566 | { | ||
567 | return __startup_pirq(data->irq); | ||
568 | } | ||
569 | |||
570 | static void shutdown_pirq(struct irq_data *data) | ||
571 | { | ||
572 | struct evtchn_close close; | ||
573 | unsigned int irq = data->irq; | ||
574 | struct irq_info *info = info_for_irq(irq); | ||
575 | int evtchn = evtchn_from_irq(irq); | ||
576 | |||
577 | BUG_ON(info->type != IRQT_PIRQ); | ||
578 | |||
579 | if (!VALID_EVTCHN(evtchn)) | ||
580 | return; | ||
581 | |||
582 | mask_evtchn(evtchn); | ||
583 | |||
584 | close.port = evtchn; | ||
585 | if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) | ||
586 | BUG(); | ||
587 | |||
588 | bind_evtchn_to_cpu(evtchn, 0); | ||
589 | evtchn_to_irq[evtchn] = -1; | ||
590 | info->evtchn = 0; | ||
591 | } | ||
592 | |||
593 | static void enable_pirq(struct irq_data *data) | ||
594 | { | ||
595 | startup_pirq(data); | ||
596 | } | ||
597 | |||
598 | static void disable_pirq(struct irq_data *data) | ||
599 | { | ||
600 | disable_dynirq(data); | ||
601 | } | ||
602 | |||
603 | static int find_irq_by_gsi(unsigned gsi) | ||
604 | { | ||
605 | struct irq_info *info; | ||
606 | |||
607 | list_for_each_entry(info, &xen_irq_list_head, list) { | ||
608 | if (info->type != IRQT_PIRQ) | ||
352 | continue; | 609 | continue; |
353 | if (irq_info[irq].type == IRQT_UNBOUND) | 610 | |
354 | break; | 611 | if (info->u.pirq.gsi == gsi) |
612 | return info->irq; | ||
355 | } | 613 | } |
356 | 614 | ||
357 | if (irq == nr_irqs) | 615 | return -1; |
358 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | 616 | } |
359 | 617 | ||
360 | desc = irq_to_desc_alloc_node(irq, 0); | 618 | int xen_allocate_pirq_gsi(unsigned gsi) |
361 | if (WARN_ON(desc == NULL)) | 619 | { |
362 | return -1; | 620 | return gsi; |
621 | } | ||
622 | |||
623 | /* | ||
624 | * Do not make any assumptions regarding the relationship between the | ||
625 | * IRQ number returned here and the Xen pirq argument. | ||
626 | * | ||
627 | * Note: We don't assign an event channel until the irq actually started | ||
628 | * up. Return an existing irq if we've already got one for the gsi. | ||
629 | * | ||
630 | * Shareable implies level triggered, not shareable implies edge | ||
631 | * triggered here. | ||
632 | */ | ||
633 | int xen_bind_pirq_gsi_to_irq(unsigned gsi, | ||
634 | unsigned pirq, int shareable, char *name) | ||
635 | { | ||
636 | int irq = -1; | ||
637 | struct physdev_irq irq_op; | ||
638 | |||
639 | spin_lock(&irq_mapping_update_lock); | ||
640 | |||
641 | irq = find_irq_by_gsi(gsi); | ||
642 | if (irq != -1) { | ||
643 | printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n", | ||
644 | irq, gsi); | ||
645 | goto out; /* XXX need refcount? */ | ||
646 | } | ||
647 | |||
648 | irq = xen_allocate_irq_gsi(gsi); | ||
649 | if (irq < 0) | ||
650 | goto out; | ||
651 | |||
652 | irq_op.irq = irq; | ||
653 | irq_op.vector = 0; | ||
654 | |||
655 | /* Only the privileged domain can do this. For non-priv, the pcifront | ||
656 | * driver provides a PCI bus that does the call to do exactly | ||
657 | * this in the priv domain. */ | ||
658 | if (xen_initial_domain() && | ||
659 | HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { | ||
660 | xen_free_irq(irq); | ||
661 | irq = -ENOSPC; | ||
662 | goto out; | ||
663 | } | ||
664 | |||
665 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF, | ||
666 | shareable ? PIRQ_SHAREABLE : 0); | ||
667 | |||
668 | pirq_query_unmask(irq); | ||
669 | /* We try to use the handler with the appropriate semantic for the | ||
670 | * type of interrupt: if the interrupt is an edge triggered | ||
671 | * interrupt we use handle_edge_irq. | ||
672 | * | ||
673 | * On the other hand if the interrupt is level triggered we use | ||
674 | * handle_fasteoi_irq like the native code does for this kind of | ||
675 | * interrupts. | ||
676 | * | ||
677 | * Depending on the Xen version, pirq_needs_eoi might return true | ||
678 | * not only for level triggered interrupts but for edge triggered | ||
679 | * interrupts too. In any case Xen always honors the eoi mechanism, | ||
680 | * not injecting any more pirqs of the same kind if the first one | ||
681 | * hasn't received an eoi yet. Therefore using the fasteoi handler | ||
682 | * is the right choice either way. | ||
683 | */ | ||
684 | if (shareable) | ||
685 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, | ||
686 | handle_fasteoi_irq, name); | ||
687 | else | ||
688 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, | ||
689 | handle_edge_irq, name); | ||
690 | |||
691 | out: | ||
692 | spin_unlock(&irq_mapping_update_lock); | ||
693 | |||
694 | return irq; | ||
695 | } | ||
696 | |||
697 | #ifdef CONFIG_PCI_MSI | ||
698 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) | ||
699 | { | ||
700 | int rc; | ||
701 | struct physdev_get_free_pirq op_get_free_pirq; | ||
702 | |||
703 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; | ||
704 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | ||
705 | |||
706 | WARN_ONCE(rc == -ENOSYS, | ||
707 | "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); | ||
708 | |||
709 | return rc ? -1 : op_get_free_pirq.pirq; | ||
710 | } | ||
711 | |||
712 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | ||
713 | int pirq, int vector, const char *name, | ||
714 | domid_t domid) | ||
715 | { | ||
716 | int irq, ret; | ||
717 | |||
718 | spin_lock(&irq_mapping_update_lock); | ||
719 | |||
720 | irq = xen_allocate_irq_dynamic(); | ||
721 | if (irq == -1) | ||
722 | goto out; | ||
723 | |||
724 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, | ||
725 | name); | ||
726 | |||
727 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0); | ||
728 | ret = irq_set_msi_desc(irq, msidesc); | ||
729 | if (ret < 0) | ||
730 | goto error_irq; | ||
731 | out: | ||
732 | spin_unlock(&irq_mapping_update_lock); | ||
733 | return irq; | ||
734 | error_irq: | ||
735 | spin_unlock(&irq_mapping_update_lock); | ||
736 | xen_free_irq(irq); | ||
737 | return -1; | ||
738 | } | ||
739 | #endif | ||
740 | |||
741 | int xen_destroy_irq(int irq) | ||
742 | { | ||
743 | struct irq_desc *desc; | ||
744 | struct physdev_unmap_pirq unmap_irq; | ||
745 | struct irq_info *info = info_for_irq(irq); | ||
746 | int rc = -ENOENT; | ||
747 | |||
748 | spin_lock(&irq_mapping_update_lock); | ||
749 | |||
750 | desc = irq_to_desc(irq); | ||
751 | if (!desc) | ||
752 | goto out; | ||
753 | |||
754 | if (xen_initial_domain()) { | ||
755 | unmap_irq.pirq = info->u.pirq.pirq; | ||
756 | unmap_irq.domid = info->u.pirq.domid; | ||
757 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | ||
758 | /* If another domain quits without making the pci_disable_msix | ||
759 | * call, the Xen hypervisor takes care of freeing the PIRQs | ||
760 | * (free_domain_pirqs). | ||
761 | */ | ||
762 | if ((rc == -ESRCH && info->u.pirq.domid != DOMID_SELF)) | ||
763 | printk(KERN_INFO "domain %d does not have %d anymore\n", | ||
764 | info->u.pirq.domid, info->u.pirq.pirq); | ||
765 | else if (rc) { | ||
766 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | ||
767 | goto out; | ||
768 | } | ||
769 | } | ||
770 | |||
771 | xen_free_irq(irq); | ||
772 | |||
773 | out: | ||
774 | spin_unlock(&irq_mapping_update_lock); | ||
775 | return rc; | ||
776 | } | ||
777 | |||
778 | int xen_irq_from_pirq(unsigned pirq) | ||
779 | { | ||
780 | int irq; | ||
781 | |||
782 | struct irq_info *info; | ||
363 | 783 | ||
364 | dynamic_irq_init_keep_chip_data(irq); | 784 | spin_lock(&irq_mapping_update_lock); |
785 | |||
786 | list_for_each_entry(info, &xen_irq_list_head, list) { | ||
787 | if (info == NULL || info->type != IRQT_PIRQ) | ||
788 | continue; | ||
789 | irq = info->irq; | ||
790 | if (info->u.pirq.pirq == pirq) | ||
791 | goto out; | ||
792 | } | ||
793 | irq = -1; | ||
794 | out: | ||
795 | spin_unlock(&irq_mapping_update_lock); | ||
365 | 796 | ||
366 | return irq; | 797 | return irq; |
367 | } | 798 | } |
368 | 799 | ||
800 | |||
801 | int xen_pirq_from_irq(unsigned irq) | ||
802 | { | ||
803 | return pirq_from_irq(irq); | ||
804 | } | ||
805 | EXPORT_SYMBOL_GPL(xen_pirq_from_irq); | ||
369 | int bind_evtchn_to_irq(unsigned int evtchn) | 806 | int bind_evtchn_to_irq(unsigned int evtchn) |
370 | { | 807 | { |
371 | int irq; | 808 | int irq; |
@@ -375,15 +812,17 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
375 | irq = evtchn_to_irq[evtchn]; | 812 | irq = evtchn_to_irq[evtchn]; |
376 | 813 | ||
377 | if (irq == -1) { | 814 | if (irq == -1) { |
378 | irq = find_unbound_irq(); | 815 | irq = xen_allocate_irq_dynamic(); |
816 | if (irq == -1) | ||
817 | goto out; | ||
379 | 818 | ||
380 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | 819 | irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, |
381 | handle_edge_irq, "event"); | 820 | handle_edge_irq, "event"); |
382 | 821 | ||
383 | evtchn_to_irq[evtchn] = irq; | 822 | xen_irq_info_evtchn_init(irq, evtchn); |
384 | irq_info[irq] = mk_evtchn_info(evtchn); | ||
385 | } | 823 | } |
386 | 824 | ||
825 | out: | ||
387 | spin_unlock(&irq_mapping_update_lock); | 826 | spin_unlock(&irq_mapping_update_lock); |
388 | 827 | ||
389 | return irq; | 828 | return irq; |
@@ -400,11 +839,11 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
400 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; | 839 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; |
401 | 840 | ||
402 | if (irq == -1) { | 841 | if (irq == -1) { |
403 | irq = find_unbound_irq(); | 842 | irq = xen_allocate_irq_dynamic(); |
404 | if (irq < 0) | 843 | if (irq < 0) |
405 | goto out; | 844 | goto out; |
406 | 845 | ||
407 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, | 846 | irq_set_chip_and_handler_name(irq, &xen_percpu_chip, |
408 | handle_percpu_irq, "ipi"); | 847 | handle_percpu_irq, "ipi"); |
409 | 848 | ||
410 | bind_ipi.vcpu = cpu; | 849 | bind_ipi.vcpu = cpu; |
@@ -413,9 +852,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
413 | BUG(); | 852 | BUG(); |
414 | evtchn = bind_ipi.port; | 853 | evtchn = bind_ipi.port; |
415 | 854 | ||
416 | evtchn_to_irq[evtchn] = irq; | 855 | xen_irq_info_ipi_init(cpu, irq, evtchn, ipi); |
417 | irq_info[irq] = mk_ipi_info(evtchn, ipi); | ||
418 | per_cpu(ipi_to_irq, cpu)[ipi] = irq; | ||
419 | 856 | ||
420 | bind_evtchn_to_cpu(evtchn, cpu); | 857 | bind_evtchn_to_cpu(evtchn, cpu); |
421 | } | 858 | } |
@@ -425,8 +862,23 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
425 | return irq; | 862 | return irq; |
426 | } | 863 | } |
427 | 864 | ||
865 | static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, | ||
866 | unsigned int remote_port) | ||
867 | { | ||
868 | struct evtchn_bind_interdomain bind_interdomain; | ||
869 | int err; | ||
870 | |||
871 | bind_interdomain.remote_dom = remote_domain; | ||
872 | bind_interdomain.remote_port = remote_port; | ||
873 | |||
874 | err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, | ||
875 | &bind_interdomain); | ||
876 | |||
877 | return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); | ||
878 | } | ||
879 | |||
428 | 880 | ||
429 | static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | 881 | int bind_virq_to_irq(unsigned int virq, unsigned int cpu) |
430 | { | 882 | { |
431 | struct evtchn_bind_virq bind_virq; | 883 | struct evtchn_bind_virq bind_virq; |
432 | int evtchn, irq; | 884 | int evtchn, irq; |
@@ -436,6 +888,13 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
436 | irq = per_cpu(virq_to_irq, cpu)[virq]; | 888 | irq = per_cpu(virq_to_irq, cpu)[virq]; |
437 | 889 | ||
438 | if (irq == -1) { | 890 | if (irq == -1) { |
891 | irq = xen_allocate_irq_dynamic(); | ||
892 | if (irq == -1) | ||
893 | goto out; | ||
894 | |||
895 | irq_set_chip_and_handler_name(irq, &xen_percpu_chip, | ||
896 | handle_percpu_irq, "virq"); | ||
897 | |||
439 | bind_virq.virq = virq; | 898 | bind_virq.virq = virq; |
440 | bind_virq.vcpu = cpu; | 899 | bind_virq.vcpu = cpu; |
441 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | 900 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, |
@@ -443,19 +902,12 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
443 | BUG(); | 902 | BUG(); |
444 | evtchn = bind_virq.port; | 903 | evtchn = bind_virq.port; |
445 | 904 | ||
446 | irq = find_unbound_irq(); | 905 | xen_irq_info_virq_init(cpu, irq, evtchn, virq); |
447 | |||
448 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, | ||
449 | handle_percpu_irq, "virq"); | ||
450 | |||
451 | evtchn_to_irq[evtchn] = irq; | ||
452 | irq_info[irq] = mk_virq_info(evtchn, virq); | ||
453 | |||
454 | per_cpu(virq_to_irq, cpu)[virq] = irq; | ||
455 | 906 | ||
456 | bind_evtchn_to_cpu(evtchn, cpu); | 907 | bind_evtchn_to_cpu(evtchn, cpu); |
457 | } | 908 | } |
458 | 909 | ||
910 | out: | ||
459 | spin_unlock(&irq_mapping_update_lock); | 911 | spin_unlock(&irq_mapping_update_lock); |
460 | 912 | ||
461 | return irq; | 913 | return irq; |
@@ -492,11 +944,9 @@ static void unbind_from_irq(unsigned int irq) | |||
492 | evtchn_to_irq[evtchn] = -1; | 944 | evtchn_to_irq[evtchn] = -1; |
493 | } | 945 | } |
494 | 946 | ||
495 | if (irq_info[irq].type != IRQT_UNBOUND) { | 947 | BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND); |
496 | irq_info[irq] = mk_unbound_info(); | ||
497 | 948 | ||
498 | dynamic_irq_cleanup(irq); | 949 | xen_free_irq(irq); |
499 | } | ||
500 | 950 | ||
501 | spin_unlock(&irq_mapping_update_lock); | 951 | spin_unlock(&irq_mapping_update_lock); |
502 | } | 952 | } |
@@ -506,10 +956,11 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, | |||
506 | unsigned long irqflags, | 956 | unsigned long irqflags, |
507 | const char *devname, void *dev_id) | 957 | const char *devname, void *dev_id) |
508 | { | 958 | { |
509 | unsigned int irq; | 959 | int irq, retval; |
510 | int retval; | ||
511 | 960 | ||
512 | irq = bind_evtchn_to_irq(evtchn); | 961 | irq = bind_evtchn_to_irq(evtchn); |
962 | if (irq < 0) | ||
963 | return irq; | ||
513 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | 964 | retval = request_irq(irq, handler, irqflags, devname, dev_id); |
514 | if (retval != 0) { | 965 | if (retval != 0) { |
515 | unbind_from_irq(irq); | 966 | unbind_from_irq(irq); |
@@ -520,14 +971,38 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, | |||
520 | } | 971 | } |
521 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); | 972 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); |
522 | 973 | ||
974 | int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, | ||
975 | unsigned int remote_port, | ||
976 | irq_handler_t handler, | ||
977 | unsigned long irqflags, | ||
978 | const char *devname, | ||
979 | void *dev_id) | ||
980 | { | ||
981 | int irq, retval; | ||
982 | |||
983 | irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port); | ||
984 | if (irq < 0) | ||
985 | return irq; | ||
986 | |||
987 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | ||
988 | if (retval != 0) { | ||
989 | unbind_from_irq(irq); | ||
990 | return retval; | ||
991 | } | ||
992 | |||
993 | return irq; | ||
994 | } | ||
995 | EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler); | ||
996 | |||
523 | int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, | 997 | int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, |
524 | irq_handler_t handler, | 998 | irq_handler_t handler, |
525 | unsigned long irqflags, const char *devname, void *dev_id) | 999 | unsigned long irqflags, const char *devname, void *dev_id) |
526 | { | 1000 | { |
527 | unsigned int irq; | 1001 | int irq, retval; |
528 | int retval; | ||
529 | 1002 | ||
530 | irq = bind_virq_to_irq(virq, cpu); | 1003 | irq = bind_virq_to_irq(virq, cpu); |
1004 | if (irq < 0) | ||
1005 | return irq; | ||
531 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | 1006 | retval = request_irq(irq, handler, irqflags, devname, dev_id); |
532 | if (retval != 0) { | 1007 | if (retval != 0) { |
533 | unbind_from_irq(irq); | 1008 | unbind_from_irq(irq); |
@@ -551,7 +1026,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, | |||
551 | if (irq < 0) | 1026 | if (irq < 0) |
552 | return irq; | 1027 | return irq; |
553 | 1028 | ||
554 | irqflags |= IRQF_NO_SUSPEND; | 1029 | irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME; |
555 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | 1030 | retval = request_irq(irq, handler, irqflags, devname, dev_id); |
556 | if (retval != 0) { | 1031 | if (retval != 0) { |
557 | unbind_from_irq(irq); | 1032 | unbind_from_irq(irq); |
@@ -579,41 +1054,75 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) | |||
579 | { | 1054 | { |
580 | struct shared_info *sh = HYPERVISOR_shared_info; | 1055 | struct shared_info *sh = HYPERVISOR_shared_info; |
581 | int cpu = smp_processor_id(); | 1056 | int cpu = smp_processor_id(); |
1057 | unsigned long *cpu_evtchn = per_cpu(cpu_evtchn_mask, cpu); | ||
582 | int i; | 1058 | int i; |
583 | unsigned long flags; | 1059 | unsigned long flags; |
584 | static DEFINE_SPINLOCK(debug_lock); | 1060 | static DEFINE_SPINLOCK(debug_lock); |
1061 | struct vcpu_info *v; | ||
585 | 1062 | ||
586 | spin_lock_irqsave(&debug_lock, flags); | 1063 | spin_lock_irqsave(&debug_lock, flags); |
587 | 1064 | ||
588 | printk("vcpu %d\n ", cpu); | 1065 | printk("\nvcpu %d\n ", cpu); |
589 | 1066 | ||
590 | for_each_online_cpu(i) { | 1067 | for_each_online_cpu(i) { |
591 | struct vcpu_info *v = per_cpu(xen_vcpu, i); | 1068 | int pending; |
592 | printk("%d: masked=%d pending=%d event_sel %08lx\n ", i, | 1069 | v = per_cpu(xen_vcpu, i); |
593 | (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask, | 1070 | pending = (get_irq_regs() && i == cpu) |
594 | v->evtchn_upcall_pending, | 1071 | ? xen_irqs_disabled(get_irq_regs()) |
595 | v->evtchn_pending_sel); | 1072 | : v->evtchn_upcall_mask; |
1073 | printk("%d: masked=%d pending=%d event_sel %0*lx\n ", i, | ||
1074 | pending, v->evtchn_upcall_pending, | ||
1075 | (int)(sizeof(v->evtchn_pending_sel)*2), | ||
1076 | v->evtchn_pending_sel); | ||
1077 | } | ||
1078 | v = per_cpu(xen_vcpu, cpu); | ||
1079 | |||
1080 | printk("\npending:\n "); | ||
1081 | for (i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) | ||
1082 | printk("%0*lx%s", (int)sizeof(sh->evtchn_pending[0])*2, | ||
1083 | sh->evtchn_pending[i], | ||
1084 | i % 8 == 0 ? "\n " : " "); | ||
1085 | printk("\nglobal mask:\n "); | ||
1086 | for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
1087 | printk("%0*lx%s", | ||
1088 | (int)(sizeof(sh->evtchn_mask[0])*2), | ||
1089 | sh->evtchn_mask[i], | ||
1090 | i % 8 == 0 ? "\n " : " "); | ||
1091 | |||
1092 | printk("\nglobally unmasked:\n "); | ||
1093 | for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
1094 | printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2), | ||
1095 | sh->evtchn_pending[i] & ~sh->evtchn_mask[i], | ||
1096 | i % 8 == 0 ? "\n " : " "); | ||
1097 | |||
1098 | printk("\nlocal cpu%d mask:\n ", cpu); | ||
1099 | for (i = (NR_EVENT_CHANNELS/BITS_PER_LONG)-1; i >= 0; i--) | ||
1100 | printk("%0*lx%s", (int)(sizeof(cpu_evtchn[0])*2), | ||
1101 | cpu_evtchn[i], | ||
1102 | i % 8 == 0 ? "\n " : " "); | ||
1103 | |||
1104 | printk("\nlocally unmasked:\n "); | ||
1105 | for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) { | ||
1106 | unsigned long pending = sh->evtchn_pending[i] | ||
1107 | & ~sh->evtchn_mask[i] | ||
1108 | & cpu_evtchn[i]; | ||
1109 | printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2), | ||
1110 | pending, i % 8 == 0 ? "\n " : " "); | ||
596 | } | 1111 | } |
597 | printk("pending:\n "); | ||
598 | for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) | ||
599 | printk("%08lx%s", sh->evtchn_pending[i], | ||
600 | i % 8 == 0 ? "\n " : " "); | ||
601 | printk("\nmasks:\n "); | ||
602 | for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
603 | printk("%08lx%s", sh->evtchn_mask[i], | ||
604 | i % 8 == 0 ? "\n " : " "); | ||
605 | |||
606 | printk("\nunmasked:\n "); | ||
607 | for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
608 | printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i], | ||
609 | i % 8 == 0 ? "\n " : " "); | ||
610 | 1112 | ||
611 | printk("\npending list:\n"); | 1113 | printk("\npending list:\n"); |
612 | for(i = 0; i < NR_EVENT_CHANNELS; i++) { | 1114 | for (i = 0; i < NR_EVENT_CHANNELS; i++) { |
613 | if (sync_test_bit(i, sh->evtchn_pending)) { | 1115 | if (sync_test_bit(i, sh->evtchn_pending)) { |
614 | printk(" %d: event %d -> irq %d\n", | 1116 | int word_idx = i / BITS_PER_LONG; |
1117 | printk(" %d: event %d -> irq %d%s%s%s\n", | ||
615 | cpu_from_evtchn(i), i, | 1118 | cpu_from_evtchn(i), i, |
616 | evtchn_to_irq[i]); | 1119 | evtchn_to_irq[i], |
1120 | sync_test_bit(word_idx, &v->evtchn_pending_sel) | ||
1121 | ? "" : " l2-clear", | ||
1122 | !sync_test_bit(i, sh->evtchn_mask) | ||
1123 | ? "" : " globally-masked", | ||
1124 | sync_test_bit(i, cpu_evtchn) | ||
1125 | ? "" : " locally-masked"); | ||
617 | } | 1126 | } |
618 | } | 1127 | } |
619 | 1128 | ||
@@ -623,6 +1132,13 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) | |||
623 | } | 1132 | } |
624 | 1133 | ||
625 | static DEFINE_PER_CPU(unsigned, xed_nesting_count); | 1134 | static DEFINE_PER_CPU(unsigned, xed_nesting_count); |
1135 | static DEFINE_PER_CPU(unsigned int, current_word_idx); | ||
1136 | static DEFINE_PER_CPU(unsigned int, current_bit_idx); | ||
1137 | |||
1138 | /* | ||
1139 | * Mask out the i least significant bits of w | ||
1140 | */ | ||
1141 | #define MASK_LSBS(w, i) (w & ((~0UL) << i)) | ||
626 | 1142 | ||
627 | /* | 1143 | /* |
628 | * Search the CPUs pending events bitmasks. For each one found, map | 1144 | * Search the CPUs pending events bitmasks. For each one found, map |
@@ -635,9 +1151,12 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count); | |||
635 | */ | 1151 | */ |
636 | static void __xen_evtchn_do_upcall(void) | 1152 | static void __xen_evtchn_do_upcall(void) |
637 | { | 1153 | { |
1154 | int start_word_idx, start_bit_idx; | ||
1155 | int word_idx, bit_idx; | ||
1156 | int i; | ||
638 | int cpu = get_cpu(); | 1157 | int cpu = get_cpu(); |
639 | struct shared_info *s = HYPERVISOR_shared_info; | 1158 | struct shared_info *s = HYPERVISOR_shared_info; |
640 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); | 1159 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); |
641 | unsigned count; | 1160 | unsigned count; |
642 | 1161 | ||
643 | do { | 1162 | do { |
@@ -645,7 +1164,7 @@ static void __xen_evtchn_do_upcall(void) | |||
645 | 1164 | ||
646 | vcpu_info->evtchn_upcall_pending = 0; | 1165 | vcpu_info->evtchn_upcall_pending = 0; |
647 | 1166 | ||
648 | if (__get_cpu_var(xed_nesting_count)++) | 1167 | if (__this_cpu_inc_return(xed_nesting_count) - 1) |
649 | goto out; | 1168 | goto out; |
650 | 1169 | ||
651 | #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ | 1170 | #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ |
@@ -653,29 +1172,83 @@ static void __xen_evtchn_do_upcall(void) | |||
653 | wmb(); | 1172 | wmb(); |
654 | #endif | 1173 | #endif |
655 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); | 1174 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); |
656 | while (pending_words != 0) { | 1175 | |
1176 | start_word_idx = __this_cpu_read(current_word_idx); | ||
1177 | start_bit_idx = __this_cpu_read(current_bit_idx); | ||
1178 | |||
1179 | word_idx = start_word_idx; | ||
1180 | |||
1181 | for (i = 0; pending_words != 0; i++) { | ||
657 | unsigned long pending_bits; | 1182 | unsigned long pending_bits; |
658 | int word_idx = __ffs(pending_words); | 1183 | unsigned long words; |
659 | pending_words &= ~(1UL << word_idx); | 1184 | |
1185 | words = MASK_LSBS(pending_words, word_idx); | ||
1186 | |||
1187 | /* | ||
1188 | * If we masked out all events, wrap to beginning. | ||
1189 | */ | ||
1190 | if (words == 0) { | ||
1191 | word_idx = 0; | ||
1192 | bit_idx = 0; | ||
1193 | continue; | ||
1194 | } | ||
1195 | word_idx = __ffs(words); | ||
1196 | |||
1197 | pending_bits = active_evtchns(cpu, s, word_idx); | ||
1198 | bit_idx = 0; /* usually scan entire word from start */ | ||
1199 | if (word_idx == start_word_idx) { | ||
1200 | /* We scan the starting word in two parts */ | ||
1201 | if (i == 0) | ||
1202 | /* 1st time: start in the middle */ | ||
1203 | bit_idx = start_bit_idx; | ||
1204 | else | ||
1205 | /* 2nd time: mask bits done already */ | ||
1206 | bit_idx &= (1UL << start_bit_idx) - 1; | ||
1207 | } | ||
660 | 1208 | ||
661 | while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) { | 1209 | do { |
662 | int bit_idx = __ffs(pending_bits); | 1210 | unsigned long bits; |
663 | int port = (word_idx * BITS_PER_LONG) + bit_idx; | 1211 | int port, irq; |
664 | int irq = evtchn_to_irq[port]; | ||
665 | struct irq_desc *desc; | 1212 | struct irq_desc *desc; |
666 | 1213 | ||
1214 | bits = MASK_LSBS(pending_bits, bit_idx); | ||
1215 | |||
1216 | /* If we masked out all events, move on. */ | ||
1217 | if (bits == 0) | ||
1218 | break; | ||
1219 | |||
1220 | bit_idx = __ffs(bits); | ||
1221 | |||
1222 | /* Process port. */ | ||
1223 | port = (word_idx * BITS_PER_LONG) + bit_idx; | ||
1224 | irq = evtchn_to_irq[port]; | ||
1225 | |||
667 | if (irq != -1) { | 1226 | if (irq != -1) { |
668 | desc = irq_to_desc(irq); | 1227 | desc = irq_to_desc(irq); |
669 | if (desc) | 1228 | if (desc) |
670 | generic_handle_irq_desc(irq, desc); | 1229 | generic_handle_irq_desc(irq, desc); |
671 | } | 1230 | } |
672 | } | 1231 | |
1232 | bit_idx = (bit_idx + 1) % BITS_PER_LONG; | ||
1233 | |||
1234 | /* Next caller starts at last processed + 1 */ | ||
1235 | __this_cpu_write(current_word_idx, | ||
1236 | bit_idx ? word_idx : | ||
1237 | (word_idx+1) % BITS_PER_LONG); | ||
1238 | __this_cpu_write(current_bit_idx, bit_idx); | ||
1239 | } while (bit_idx != 0); | ||
1240 | |||
1241 | /* Scan start_l1i twice; all others once. */ | ||
1242 | if ((word_idx != start_word_idx) || (i != 0)) | ||
1243 | pending_words &= ~(1UL << word_idx); | ||
1244 | |||
1245 | word_idx = (word_idx + 1) % BITS_PER_LONG; | ||
673 | } | 1246 | } |
674 | 1247 | ||
675 | BUG_ON(!irqs_disabled()); | 1248 | BUG_ON(!irqs_disabled()); |
676 | 1249 | ||
677 | count = __get_cpu_var(xed_nesting_count); | 1250 | count = __this_cpu_read(xed_nesting_count); |
678 | __get_cpu_var(xed_nesting_count) = 0; | 1251 | __this_cpu_write(xed_nesting_count, 0); |
679 | } while (count != 1 || vcpu_info->evtchn_upcall_pending); | 1252 | } while (count != 1 || vcpu_info->evtchn_upcall_pending); |
680 | 1253 | ||
681 | out: | 1254 | out: |
@@ -719,8 +1292,7 @@ void rebind_evtchn_irq(int evtchn, int irq) | |||
719 | so there should be a proper type */ | 1292 | so there should be a proper type */ |
720 | BUG_ON(info->type == IRQT_UNBOUND); | 1293 | BUG_ON(info->type == IRQT_UNBOUND); |
721 | 1294 | ||
722 | evtchn_to_irq[evtchn] = irq; | 1295 | xen_irq_info_evtchn_init(irq, evtchn); |
723 | irq_info[irq] = mk_evtchn_info(evtchn); | ||
724 | 1296 | ||
725 | spin_unlock(&irq_mapping_update_lock); | 1297 | spin_unlock(&irq_mapping_update_lock); |
726 | 1298 | ||
@@ -737,10 +1309,14 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
737 | struct evtchn_bind_vcpu bind_vcpu; | 1309 | struct evtchn_bind_vcpu bind_vcpu; |
738 | int evtchn = evtchn_from_irq(irq); | 1310 | int evtchn = evtchn_from_irq(irq); |
739 | 1311 | ||
740 | /* events delivered via platform PCI interrupts are always | 1312 | if (!VALID_EVTCHN(evtchn)) |
741 | * routed to vcpu 0 */ | 1313 | return -1; |
742 | if (!VALID_EVTCHN(evtchn) || | 1314 | |
743 | (xen_hvm_domain() && !xen_have_vector_callback)) | 1315 | /* |
1316 | * Events delivered via platform PCI interrupts are always | ||
1317 | * routed to vcpu 0 and hence cannot be rebound. | ||
1318 | */ | ||
1319 | if (xen_hvm_domain() && !xen_have_vector_callback) | ||
744 | return -1; | 1320 | return -1; |
745 | 1321 | ||
746 | /* Send future instances of this interrupt to other vcpu. */ | 1322 | /* Send future instances of this interrupt to other vcpu. */ |
@@ -758,11 +1334,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
758 | return 0; | 1334 | return 0; |
759 | } | 1335 | } |
760 | 1336 | ||
761 | static int set_affinity_irq(unsigned irq, const struct cpumask *dest) | 1337 | static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, |
1338 | bool force) | ||
762 | { | 1339 | { |
763 | unsigned tcpu = cpumask_first(dest); | 1340 | unsigned tcpu = cpumask_first(dest); |
764 | 1341 | ||
765 | return rebind_irq_to_cpu(irq, tcpu); | 1342 | return rebind_irq_to_cpu(data->irq, tcpu); |
766 | } | 1343 | } |
767 | 1344 | ||
768 | int resend_irq_on_evtchn(unsigned int irq) | 1345 | int resend_irq_on_evtchn(unsigned int irq) |
@@ -781,35 +1358,41 @@ int resend_irq_on_evtchn(unsigned int irq) | |||
781 | return 1; | 1358 | return 1; |
782 | } | 1359 | } |
783 | 1360 | ||
784 | static void enable_dynirq(unsigned int irq) | 1361 | static void enable_dynirq(struct irq_data *data) |
785 | { | 1362 | { |
786 | int evtchn = evtchn_from_irq(irq); | 1363 | int evtchn = evtchn_from_irq(data->irq); |
787 | 1364 | ||
788 | if (VALID_EVTCHN(evtchn)) | 1365 | if (VALID_EVTCHN(evtchn)) |
789 | unmask_evtchn(evtchn); | 1366 | unmask_evtchn(evtchn); |
790 | } | 1367 | } |
791 | 1368 | ||
792 | static void disable_dynirq(unsigned int irq) | 1369 | static void disable_dynirq(struct irq_data *data) |
793 | { | 1370 | { |
794 | int evtchn = evtchn_from_irq(irq); | 1371 | int evtchn = evtchn_from_irq(data->irq); |
795 | 1372 | ||
796 | if (VALID_EVTCHN(evtchn)) | 1373 | if (VALID_EVTCHN(evtchn)) |
797 | mask_evtchn(evtchn); | 1374 | mask_evtchn(evtchn); |
798 | } | 1375 | } |
799 | 1376 | ||
800 | static void ack_dynirq(unsigned int irq) | 1377 | static void ack_dynirq(struct irq_data *data) |
801 | { | 1378 | { |
802 | int evtchn = evtchn_from_irq(irq); | 1379 | int evtchn = evtchn_from_irq(data->irq); |
803 | 1380 | ||
804 | move_native_irq(irq); | 1381 | irq_move_irq(data); |
805 | 1382 | ||
806 | if (VALID_EVTCHN(evtchn)) | 1383 | if (VALID_EVTCHN(evtchn)) |
807 | clear_evtchn(evtchn); | 1384 | clear_evtchn(evtchn); |
808 | } | 1385 | } |
809 | 1386 | ||
810 | static int retrigger_dynirq(unsigned int irq) | 1387 | static void mask_ack_dynirq(struct irq_data *data) |
811 | { | 1388 | { |
812 | int evtchn = evtchn_from_irq(irq); | 1389 | disable_dynirq(data); |
1390 | ack_dynirq(data); | ||
1391 | } | ||
1392 | |||
1393 | static int retrigger_dynirq(struct irq_data *data) | ||
1394 | { | ||
1395 | int evtchn = evtchn_from_irq(data->irq); | ||
813 | struct shared_info *sh = HYPERVISOR_shared_info; | 1396 | struct shared_info *sh = HYPERVISOR_shared_info; |
814 | int ret = 0; | 1397 | int ret = 0; |
815 | 1398 | ||
@@ -826,6 +1409,44 @@ static int retrigger_dynirq(unsigned int irq) | |||
826 | return ret; | 1409 | return ret; |
827 | } | 1410 | } |
828 | 1411 | ||
1412 | static void restore_pirqs(void) | ||
1413 | { | ||
1414 | int pirq, rc, irq, gsi; | ||
1415 | struct physdev_map_pirq map_irq; | ||
1416 | struct irq_info *info; | ||
1417 | |||
1418 | list_for_each_entry(info, &xen_irq_list_head, list) { | ||
1419 | if (info->type != IRQT_PIRQ) | ||
1420 | continue; | ||
1421 | |||
1422 | pirq = info->u.pirq.pirq; | ||
1423 | gsi = info->u.pirq.gsi; | ||
1424 | irq = info->irq; | ||
1425 | |||
1426 | /* save/restore of PT devices doesn't work, so at this point the | ||
1427 | * only devices present are GSI based emulated devices */ | ||
1428 | if (!gsi) | ||
1429 | continue; | ||
1430 | |||
1431 | map_irq.domid = DOMID_SELF; | ||
1432 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
1433 | map_irq.index = gsi; | ||
1434 | map_irq.pirq = pirq; | ||
1435 | |||
1436 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
1437 | if (rc) { | ||
1438 | printk(KERN_WARNING "xen map irq failed gsi=%d irq=%d pirq=%d rc=%d\n", | ||
1439 | gsi, irq, pirq, rc); | ||
1440 | xen_free_irq(irq); | ||
1441 | continue; | ||
1442 | } | ||
1443 | |||
1444 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); | ||
1445 | |||
1446 | __startup_pirq(irq); | ||
1447 | } | ||
1448 | } | ||
1449 | |||
829 | static void restore_cpu_virqs(unsigned int cpu) | 1450 | static void restore_cpu_virqs(unsigned int cpu) |
830 | { | 1451 | { |
831 | struct evtchn_bind_virq bind_virq; | 1452 | struct evtchn_bind_virq bind_virq; |
@@ -846,12 +1467,8 @@ static void restore_cpu_virqs(unsigned int cpu) | |||
846 | evtchn = bind_virq.port; | 1467 | evtchn = bind_virq.port; |
847 | 1468 | ||
848 | /* Record the new mapping. */ | 1469 | /* Record the new mapping. */ |
849 | evtchn_to_irq[evtchn] = irq; | 1470 | xen_irq_info_virq_init(cpu, irq, evtchn, virq); |
850 | irq_info[irq] = mk_virq_info(evtchn, virq); | ||
851 | bind_evtchn_to_cpu(evtchn, cpu); | 1471 | bind_evtchn_to_cpu(evtchn, cpu); |
852 | |||
853 | /* Ready for use. */ | ||
854 | unmask_evtchn(evtchn); | ||
855 | } | 1472 | } |
856 | } | 1473 | } |
857 | 1474 | ||
@@ -874,13 +1491,8 @@ static void restore_cpu_ipis(unsigned int cpu) | |||
874 | evtchn = bind_ipi.port; | 1491 | evtchn = bind_ipi.port; |
875 | 1492 | ||
876 | /* Record the new mapping. */ | 1493 | /* Record the new mapping. */ |
877 | evtchn_to_irq[evtchn] = irq; | 1494 | xen_irq_info_ipi_init(cpu, irq, evtchn, ipi); |
878 | irq_info[irq] = mk_ipi_info(evtchn, ipi); | ||
879 | bind_evtchn_to_cpu(evtchn, cpu); | 1495 | bind_evtchn_to_cpu(evtchn, cpu); |
880 | |||
881 | /* Ready for use. */ | ||
882 | unmask_evtchn(evtchn); | ||
883 | |||
884 | } | 1496 | } |
885 | } | 1497 | } |
886 | 1498 | ||
@@ -892,7 +1504,7 @@ void xen_clear_irq_pending(int irq) | |||
892 | if (VALID_EVTCHN(evtchn)) | 1504 | if (VALID_EVTCHN(evtchn)) |
893 | clear_evtchn(evtchn); | 1505 | clear_evtchn(evtchn); |
894 | } | 1506 | } |
895 | 1507 | EXPORT_SYMBOL(xen_clear_irq_pending); | |
896 | void xen_set_irq_pending(int irq) | 1508 | void xen_set_irq_pending(int irq) |
897 | { | 1509 | { |
898 | int evtchn = evtchn_from_irq(irq); | 1510 | int evtchn = evtchn_from_irq(irq); |
@@ -912,9 +1524,9 @@ bool xen_test_irq_pending(int irq) | |||
912 | return ret; | 1524 | return ret; |
913 | } | 1525 | } |
914 | 1526 | ||
915 | /* Poll waiting for an irq to become pending. In the usual case, the | 1527 | /* Poll waiting for an irq to become pending with timeout. In the usual case, |
916 | irq will be disabled so it won't deliver an interrupt. */ | 1528 | * the irq will be disabled so it won't deliver an interrupt. */ |
917 | void xen_poll_irq(int irq) | 1529 | void xen_poll_irq_timeout(int irq, u64 timeout) |
918 | { | 1530 | { |
919 | evtchn_port_t evtchn = evtchn_from_irq(irq); | 1531 | evtchn_port_t evtchn = evtchn_from_irq(irq); |
920 | 1532 | ||
@@ -922,17 +1534,37 @@ void xen_poll_irq(int irq) | |||
922 | struct sched_poll poll; | 1534 | struct sched_poll poll; |
923 | 1535 | ||
924 | poll.nr_ports = 1; | 1536 | poll.nr_ports = 1; |
925 | poll.timeout = 0; | 1537 | poll.timeout = timeout; |
926 | set_xen_guest_handle(poll.ports, &evtchn); | 1538 | set_xen_guest_handle(poll.ports, &evtchn); |
927 | 1539 | ||
928 | if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0) | 1540 | if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0) |
929 | BUG(); | 1541 | BUG(); |
930 | } | 1542 | } |
931 | } | 1543 | } |
1544 | EXPORT_SYMBOL(xen_poll_irq_timeout); | ||
1545 | /* Poll waiting for an irq to become pending. In the usual case, the | ||
1546 | * irq will be disabled so it won't deliver an interrupt. */ | ||
1547 | void xen_poll_irq(int irq) | ||
1548 | { | ||
1549 | xen_poll_irq_timeout(irq, 0 /* no timeout */); | ||
1550 | } | ||
1551 | |||
1552 | /* Check whether the IRQ line is shared with other guests. */ | ||
1553 | int xen_test_irq_shared(int irq) | ||
1554 | { | ||
1555 | struct irq_info *info = info_for_irq(irq); | ||
1556 | struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq }; | ||
1557 | |||
1558 | if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) | ||
1559 | return 0; | ||
1560 | return !(irq_status.flags & XENIRQSTAT_shared); | ||
1561 | } | ||
1562 | EXPORT_SYMBOL_GPL(xen_test_irq_shared); | ||
932 | 1563 | ||
933 | void xen_irq_resume(void) | 1564 | void xen_irq_resume(void) |
934 | { | 1565 | { |
935 | unsigned int cpu, irq, evtchn; | 1566 | unsigned int cpu, evtchn; |
1567 | struct irq_info *info; | ||
936 | 1568 | ||
937 | init_evtchn_cpu_bindings(); | 1569 | init_evtchn_cpu_bindings(); |
938 | 1570 | ||
@@ -941,8 +1573,8 @@ void xen_irq_resume(void) | |||
941 | mask_evtchn(evtchn); | 1573 | mask_evtchn(evtchn); |
942 | 1574 | ||
943 | /* No IRQ <-> event-channel mappings. */ | 1575 | /* No IRQ <-> event-channel mappings. */ |
944 | for (irq = 0; irq < nr_irqs; irq++) | 1576 | list_for_each_entry(info, &xen_irq_list_head, list) |
945 | irq_info[irq].evtchn = 0; /* zap event-channel binding */ | 1577 | info->evtchn = 0; /* zap event-channel binding */ |
946 | 1578 | ||
947 | for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) | 1579 | for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) |
948 | evtchn_to_irq[evtchn] = -1; | 1580 | evtchn_to_irq[evtchn] = -1; |
@@ -951,28 +1583,52 @@ void xen_irq_resume(void) | |||
951 | restore_cpu_virqs(cpu); | 1583 | restore_cpu_virqs(cpu); |
952 | restore_cpu_ipis(cpu); | 1584 | restore_cpu_ipis(cpu); |
953 | } | 1585 | } |
1586 | |||
1587 | restore_pirqs(); | ||
954 | } | 1588 | } |
955 | 1589 | ||
956 | static struct irq_chip xen_dynamic_chip __read_mostly = { | 1590 | static struct irq_chip xen_dynamic_chip __read_mostly = { |
957 | .name = "xen-dyn", | 1591 | .name = "xen-dyn", |
1592 | |||
1593 | .irq_disable = disable_dynirq, | ||
1594 | .irq_mask = disable_dynirq, | ||
1595 | .irq_unmask = enable_dynirq, | ||
1596 | |||
1597 | .irq_ack = ack_dynirq, | ||
1598 | .irq_mask_ack = mask_ack_dynirq, | ||
1599 | |||
1600 | .irq_set_affinity = set_affinity_irq, | ||
1601 | .irq_retrigger = retrigger_dynirq, | ||
1602 | }; | ||
958 | 1603 | ||
959 | .disable = disable_dynirq, | 1604 | static struct irq_chip xen_pirq_chip __read_mostly = { |
960 | .mask = disable_dynirq, | 1605 | .name = "xen-pirq", |
961 | .unmask = enable_dynirq, | ||
962 | 1606 | ||
963 | .ack = ack_dynirq, | 1607 | .irq_startup = startup_pirq, |
964 | .set_affinity = set_affinity_irq, | 1608 | .irq_shutdown = shutdown_pirq, |
965 | .retrigger = retrigger_dynirq, | 1609 | .irq_enable = enable_pirq, |
1610 | .irq_disable = disable_pirq, | ||
1611 | |||
1612 | .irq_mask = disable_dynirq, | ||
1613 | .irq_unmask = enable_dynirq, | ||
1614 | |||
1615 | .irq_ack = eoi_pirq, | ||
1616 | .irq_eoi = eoi_pirq, | ||
1617 | .irq_mask_ack = mask_ack_pirq, | ||
1618 | |||
1619 | .irq_set_affinity = set_affinity_irq, | ||
1620 | |||
1621 | .irq_retrigger = retrigger_dynirq, | ||
966 | }; | 1622 | }; |
967 | 1623 | ||
968 | static struct irq_chip xen_percpu_chip __read_mostly = { | 1624 | static struct irq_chip xen_percpu_chip __read_mostly = { |
969 | .name = "xen-percpu", | 1625 | .name = "xen-percpu", |
970 | 1626 | ||
971 | .disable = disable_dynirq, | 1627 | .irq_disable = disable_dynirq, |
972 | .mask = disable_dynirq, | 1628 | .irq_mask = disable_dynirq, |
973 | .unmask = enable_dynirq, | 1629 | .irq_unmask = enable_dynirq, |
974 | 1630 | ||
975 | .ack = ack_dynirq, | 1631 | .irq_ack = ack_dynirq, |
976 | }; | 1632 | }; |
977 | 1633 | ||
978 | int xen_set_callback_via(uint64_t via) | 1634 | int xen_set_callback_via(uint64_t via) |
@@ -1017,9 +1673,10 @@ void __init xen_init_IRQ(void) | |||
1017 | { | 1673 | { |
1018 | int i; | 1674 | int i; |
1019 | 1675 | ||
1020 | cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s), | 1676 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), |
1021 | GFP_KERNEL); | 1677 | GFP_KERNEL); |
1022 | BUG_ON(cpu_evtchn_mask_p == NULL); | 1678 | for (i = 0; i < NR_EVENT_CHANNELS; i++) |
1679 | evtchn_to_irq[i] = -1; | ||
1023 | 1680 | ||
1024 | init_evtchn_cpu_bindings(); | 1681 | init_evtchn_cpu_bindings(); |
1025 | 1682 | ||
@@ -1030,7 +1687,12 @@ void __init xen_init_IRQ(void) | |||
1030 | if (xen_hvm_domain()) { | 1687 | if (xen_hvm_domain()) { |
1031 | xen_callback_vector(); | 1688 | xen_callback_vector(); |
1032 | native_init_IRQ(); | 1689 | native_init_IRQ(); |
1690 | /* pci_xen_hvm_init must be called after native_init_IRQ so that | ||
1691 | * __acpi_register_gsi can point at the right function */ | ||
1692 | pci_xen_hvm_init(); | ||
1033 | } else { | 1693 | } else { |
1034 | irq_ctx_init(smp_processor_id()); | 1694 | irq_ctx_init(smp_processor_id()); |
1695 | if (xen_initial_domain()) | ||
1696 | xen_setup_pirqs(); | ||
1035 | } | 1697 | } |
1036 | } | 1698 | } |