aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c184
1 files changed, 135 insertions, 49 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 2c8d710713f5..0541e07d4f67 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -52,18 +52,8 @@ static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
52/* IRQ <-> IPI mapping */ 52/* IRQ <-> IPI mapping */
53static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1}; 53static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
54 54
55/* Packed IRQ information: binding type, sub-type index, and event channel. */ 55/* Interrupt types. */
56struct packed_irq 56enum xen_irq_type {
57{
58 unsigned short evtchn;
59 unsigned char index;
60 unsigned char type;
61};
62
63static struct packed_irq irq_info[NR_IRQS];
64
65/* Binding types. */
66enum {
67 IRQT_UNBOUND, 57 IRQT_UNBOUND,
68 IRQT_PIRQ, 58 IRQT_PIRQ,
69 IRQT_VIRQ, 59 IRQT_VIRQ,
@@ -71,8 +61,34 @@ enum {
71 IRQT_EVTCHN 61 IRQT_EVTCHN
72}; 62};
73 63
74/* Convenient shorthand for packed representation of an unbound IRQ. */ 64/*
75#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0) 65 * Packed IRQ information:
66 * type - enum xen_irq_type
67 * event channel - irq->event channel mapping
68 * cpu - cpu this event channel is bound to
69 * index - type-specific information:
70 * PIRQ - vector, with MSB being "needs EIO"
71 * VIRQ - virq number
72 * IPI - IPI vector
73 * EVTCHN -
74 */
75struct irq_info
76{
77 enum xen_irq_type type; /* type */
78 unsigned short evtchn; /* event channel */
79 unsigned short cpu; /* cpu bound */
80
81 union {
82 unsigned short virq;
83 enum ipi_vector ipi;
84 struct {
85 unsigned short gsi;
86 unsigned short vector;
87 } pirq;
88 } u;
89};
90
91static struct irq_info irq_info[NR_IRQS];
76 92
77static int evtchn_to_irq[NR_EVENT_CHANNELS] = { 93static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
78 [0 ... NR_EVENT_CHANNELS-1] = -1 94 [0 ... NR_EVENT_CHANNELS-1] = -1
@@ -85,7 +101,6 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
85{ 101{
86 return cpu_evtchn_mask_p[cpu].bits; 102 return cpu_evtchn_mask_p[cpu].bits;
87} 103}
88static u8 cpu_evtchn[NR_EVENT_CHANNELS];
89 104
90/* Reference counts for bindings to IRQs. */ 105/* Reference counts for bindings to IRQs. */
91static int irq_bindcount[NR_IRQS]; 106static int irq_bindcount[NR_IRQS];
@@ -96,27 +111,107 @@ static int irq_bindcount[NR_IRQS];
96static struct irq_chip xen_dynamic_chip; 111static struct irq_chip xen_dynamic_chip;
97 112
98/* Constructor for packed IRQ information. */ 113/* Constructor for packed IRQ information. */
99static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn) 114static struct irq_info mk_unbound_info(void)
115{
116 return (struct irq_info) { .type = IRQT_UNBOUND };
117}
118
119static struct irq_info mk_evtchn_info(unsigned short evtchn)
120{
121 return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn };
122}
123
124static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi)
100{ 125{
101 return (struct packed_irq) { evtchn, index, type }; 126 return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn,
127 .u.ipi = ipi };
128}
129
130static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq)
131{
132 return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn,
133 .u.virq = virq };
134}
135
136static struct irq_info mk_pirq_info(unsigned short evtchn,
137 unsigned short gsi, unsigned short vector)
138{
139 return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
140 .u.pirq = { .gsi = gsi, .vector = vector } };
102} 141}
103 142
104/* 143/*
105 * Accessors for packed IRQ information. 144 * Accessors for packed IRQ information.
106 */ 145 */
107static inline unsigned int evtchn_from_irq(int irq) 146static struct irq_info *info_for_irq(unsigned irq)
108{ 147{
109 return irq_info[irq].evtchn; 148 return &irq_info[irq];
110} 149}
111 150
112static inline unsigned int index_from_irq(int irq) 151static unsigned int evtchn_from_irq(unsigned irq)
113{ 152{
114 return irq_info[irq].index; 153 return info_for_irq(irq)->evtchn;
115} 154}
116 155
117static inline unsigned int type_from_irq(int irq) 156static enum ipi_vector ipi_from_irq(unsigned irq)
118{ 157{
119 return irq_info[irq].type; 158 struct irq_info *info = info_for_irq(irq);
159
160 BUG_ON(info == NULL);
161 BUG_ON(info->type != IRQT_IPI);
162
163 return info->u.ipi;
164}
165
166static unsigned virq_from_irq(unsigned irq)
167{
168 struct irq_info *info = info_for_irq(irq);
169
170 BUG_ON(info == NULL);
171 BUG_ON(info->type != IRQT_VIRQ);
172
173 return info->u.virq;
174}
175
176static unsigned gsi_from_irq(unsigned irq)
177{
178 struct irq_info *info = info_for_irq(irq);
179
180 BUG_ON(info == NULL);
181 BUG_ON(info->type != IRQT_PIRQ);
182
183 return info->u.pirq.gsi;
184}
185
186static unsigned vector_from_irq(unsigned irq)
187{
188 struct irq_info *info = info_for_irq(irq);
189
190 BUG_ON(info == NULL);
191 BUG_ON(info->type != IRQT_PIRQ);
192
193 return info->u.pirq.vector;
194}
195
196static enum xen_irq_type type_from_irq(unsigned irq)
197{
198 return info_for_irq(irq)->type;
199}
200
201static unsigned cpu_from_irq(unsigned irq)
202{
203 return info_for_irq(irq)->cpu;
204}
205
206static unsigned int cpu_from_evtchn(unsigned int evtchn)
207{
208 int irq = evtchn_to_irq[evtchn];
209 unsigned ret = 0;
210
211 if (irq != -1)
212 ret = cpu_from_irq(irq);
213
214 return ret;
120} 215}
121 216
122static inline unsigned long active_evtchns(unsigned int cpu, 217static inline unsigned long active_evtchns(unsigned int cpu,
@@ -137,10 +232,10 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
137 cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); 232 cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
138#endif 233#endif
139 234
140 __clear_bit(chn, cpu_evtchn_mask(cpu_evtchn[chn])); 235 __clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
141 __set_bit(chn, cpu_evtchn_mask(cpu)); 236 __set_bit(chn, cpu_evtchn_mask(cpu));
142 237
143 cpu_evtchn[chn] = cpu; 238 irq_info[irq].cpu = cpu;
144} 239}
145 240
146static void init_evtchn_cpu_bindings(void) 241static void init_evtchn_cpu_bindings(void)
@@ -155,15 +250,9 @@ static void init_evtchn_cpu_bindings(void)
155 } 250 }
156#endif 251#endif
157 252
158 memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
159 memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); 253 memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0)));
160} 254}
161 255
162static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
163{
164 return cpu_evtchn[evtchn];
165}
166
167static inline void clear_evtchn(int port) 256static inline void clear_evtchn(int port)
168{ 257{
169 struct shared_info *s = HYPERVISOR_shared_info; 258 struct shared_info *s = HYPERVISOR_shared_info;
@@ -253,6 +342,8 @@ static int find_unbound_irq(void)
253 if (WARN_ON(desc == NULL)) 342 if (WARN_ON(desc == NULL))
254 return -1; 343 return -1;
255 344
345 dynamic_irq_init(irq);
346
256 return irq; 347 return irq;
257} 348}
258 349
@@ -267,12 +358,11 @@ int bind_evtchn_to_irq(unsigned int evtchn)
267 if (irq == -1) { 358 if (irq == -1) {
268 irq = find_unbound_irq(); 359 irq = find_unbound_irq();
269 360
270 dynamic_irq_init(irq);
271 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, 361 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
272 handle_level_irq, "event"); 362 handle_level_irq, "event");
273 363
274 evtchn_to_irq[evtchn] = irq; 364 evtchn_to_irq[evtchn] = irq;
275 irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); 365 irq_info[irq] = mk_evtchn_info(evtchn);
276 } 366 }
277 367
278 irq_bindcount[irq]++; 368 irq_bindcount[irq]++;
@@ -296,7 +386,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
296 if (irq < 0) 386 if (irq < 0)
297 goto out; 387 goto out;
298 388
299 dynamic_irq_init(irq);
300 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, 389 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
301 handle_level_irq, "ipi"); 390 handle_level_irq, "ipi");
302 391
@@ -307,7 +396,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
307 evtchn = bind_ipi.port; 396 evtchn = bind_ipi.port;
308 397
309 evtchn_to_irq[evtchn] = irq; 398 evtchn_to_irq[evtchn] = irq;
310 irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); 399 irq_info[irq] = mk_ipi_info(evtchn, ipi);
311 400
312 per_cpu(ipi_to_irq, cpu)[ipi] = irq; 401 per_cpu(ipi_to_irq, cpu)[ipi] = irq;
313 402
@@ -341,12 +430,11 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
341 430
342 irq = find_unbound_irq(); 431 irq = find_unbound_irq();
343 432
344 dynamic_irq_init(irq);
345 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, 433 set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
346 handle_level_irq, "virq"); 434 handle_level_irq, "virq");
347 435
348 evtchn_to_irq[evtchn] = irq; 436 evtchn_to_irq[evtchn] = irq;
349 irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); 437 irq_info[irq] = mk_virq_info(evtchn, virq);
350 438
351 per_cpu(virq_to_irq, cpu)[virq] = irq; 439 per_cpu(virq_to_irq, cpu)[virq] = irq;
352 440
@@ -375,11 +463,11 @@ static void unbind_from_irq(unsigned int irq)
375 switch (type_from_irq(irq)) { 463 switch (type_from_irq(irq)) {
376 case IRQT_VIRQ: 464 case IRQT_VIRQ:
377 per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) 465 per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
378 [index_from_irq(irq)] = -1; 466 [virq_from_irq(irq)] = -1;
379 break; 467 break;
380 case IRQT_IPI: 468 case IRQT_IPI:
381 per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn)) 469 per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
382 [index_from_irq(irq)] = -1; 470 [ipi_from_irq(irq)] = -1;
383 break; 471 break;
384 default: 472 default:
385 break; 473 break;
@@ -389,7 +477,7 @@ static void unbind_from_irq(unsigned int irq)
389 bind_evtchn_to_cpu(evtchn, 0); 477 bind_evtchn_to_cpu(evtchn, 0);
390 478
391 evtchn_to_irq[evtchn] = -1; 479 evtchn_to_irq[evtchn] = -1;
392 irq_info[irq] = IRQ_UNBOUND; 480 irq_info[irq] = mk_unbound_info();
393 481
394 dynamic_irq_cleanup(irq); 482 dynamic_irq_cleanup(irq);
395 } 483 }
@@ -507,8 +595,8 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
507 for(i = 0; i < NR_EVENT_CHANNELS; i++) { 595 for(i = 0; i < NR_EVENT_CHANNELS; i++) {
508 if (sync_test_bit(i, sh->evtchn_pending)) { 596 if (sync_test_bit(i, sh->evtchn_pending)) {
509 printk(" %d: event %d -> irq %d\n", 597 printk(" %d: event %d -> irq %d\n",
510 cpu_evtchn[i], i, 598 cpu_from_evtchn(i), i,
511 evtchn_to_irq[i]); 599 evtchn_to_irq[i]);
512 } 600 }
513 } 601 }
514 602
@@ -606,7 +694,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
606 BUG_ON(irq_bindcount[irq] == 0); 694 BUG_ON(irq_bindcount[irq] == 0);
607 695
608 evtchn_to_irq[evtchn] = irq; 696 evtchn_to_irq[evtchn] = irq;
609 irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); 697 irq_info[irq] = mk_evtchn_info(evtchn);
610 698
611 spin_unlock(&irq_mapping_update_lock); 699 spin_unlock(&irq_mapping_update_lock);
612 700
@@ -716,8 +804,7 @@ static void restore_cpu_virqs(unsigned int cpu)
716 if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) 804 if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
717 continue; 805 continue;
718 806
719 BUG_ON(irq_info[irq].type != IRQT_VIRQ); 807 BUG_ON(virq_from_irq(irq) != virq);
720 BUG_ON(irq_info[irq].index != virq);
721 808
722 /* Get a new binding from Xen. */ 809 /* Get a new binding from Xen. */
723 bind_virq.virq = virq; 810 bind_virq.virq = virq;
@@ -729,7 +816,7 @@ static void restore_cpu_virqs(unsigned int cpu)
729 816
730 /* Record the new mapping. */ 817 /* Record the new mapping. */
731 evtchn_to_irq[evtchn] = irq; 818 evtchn_to_irq[evtchn] = irq;
732 irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); 819 irq_info[irq] = mk_virq_info(evtchn, virq);
733 bind_evtchn_to_cpu(evtchn, cpu); 820 bind_evtchn_to_cpu(evtchn, cpu);
734 821
735 /* Ready for use. */ 822 /* Ready for use. */
@@ -746,8 +833,7 @@ static void restore_cpu_ipis(unsigned int cpu)
746 if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) 833 if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
747 continue; 834 continue;
748 835
749 BUG_ON(irq_info[irq].type != IRQT_IPI); 836 BUG_ON(ipi_from_irq(irq) != ipi);
750 BUG_ON(irq_info[irq].index != ipi);
751 837
752 /* Get a new binding from Xen. */ 838 /* Get a new binding from Xen. */
753 bind_ipi.vcpu = cpu; 839 bind_ipi.vcpu = cpu;
@@ -758,7 +844,7 @@ static void restore_cpu_ipis(unsigned int cpu)
758 844
759 /* Record the new mapping. */ 845 /* Record the new mapping. */
760 evtchn_to_irq[evtchn] = irq; 846 evtchn_to_irq[evtchn] = irq;
761 irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); 847 irq_info[irq] = mk_ipi_info(evtchn, ipi);
762 bind_evtchn_to_cpu(evtchn, cpu); 848 bind_evtchn_to_cpu(evtchn, cpu);
763 849
764 /* Ready for use. */ 850 /* Ready for use. */