diff options
| author | Jeremy Fitzhardinge <jeremy@goop.org> | 2009-02-06 17:09:44 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 06:17:45 -0500 |
| commit | ced40d0f3e8833bb8d7d8e2cbfac7da0bf7008c4 (patch) | |
| tree | 980247c2e6e3a48f7b1f1447af172da0f7de9800 | |
| parent | 792dc4f6cdacf50d3f2b93756d282fc04ee34bd5 (diff) | |
xen: pack all irq-related info together
Put all irq info into one struct. Also, use a union to keep
event channel type-specific information, rather than overloading the
index field.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | drivers/xen/events.c | 184 |
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 */ |
| 53 | static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1}; | 53 | static 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. */ |
| 56 | struct packed_irq | 56 | enum xen_irq_type { |
| 57 | { | ||
| 58 | unsigned short evtchn; | ||
| 59 | unsigned char index; | ||
| 60 | unsigned char type; | ||
| 61 | }; | ||
| 62 | |||
| 63 | static struct packed_irq irq_info[NR_IRQS]; | ||
| 64 | |||
| 65 | /* Binding types. */ | ||
| 66 | enum { | ||
| 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 | */ | ||
| 75 | struct 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 | |||
| 91 | static struct irq_info irq_info[NR_IRQS]; | ||
| 76 | 92 | ||
| 77 | static int evtchn_to_irq[NR_EVENT_CHANNELS] = { | 93 | static 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 | } |
| 88 | static u8 cpu_evtchn[NR_EVENT_CHANNELS]; | ||
| 89 | 104 | ||
| 90 | /* Reference counts for bindings to IRQs. */ | 105 | /* Reference counts for bindings to IRQs. */ |
| 91 | static int irq_bindcount[NR_IRQS]; | 106 | static int irq_bindcount[NR_IRQS]; |
| @@ -96,27 +111,107 @@ static int irq_bindcount[NR_IRQS]; | |||
| 96 | static struct irq_chip xen_dynamic_chip; | 111 | static struct irq_chip xen_dynamic_chip; |
| 97 | 112 | ||
| 98 | /* Constructor for packed IRQ information. */ | 113 | /* Constructor for packed IRQ information. */ |
| 99 | static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn) | 114 | static struct irq_info mk_unbound_info(void) |
| 115 | { | ||
| 116 | return (struct irq_info) { .type = IRQT_UNBOUND }; | ||
| 117 | } | ||
| 118 | |||
| 119 | static struct irq_info mk_evtchn_info(unsigned short evtchn) | ||
| 120 | { | ||
| 121 | return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn }; | ||
| 122 | } | ||
| 123 | |||
| 124 | static 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 | |||
| 130 | static 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 | |||
| 136 | static 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 | */ |
| 107 | static inline unsigned int evtchn_from_irq(int irq) | 146 | static 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 | ||
| 112 | static inline unsigned int index_from_irq(int irq) | 151 | static 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 | ||
| 117 | static inline unsigned int type_from_irq(int irq) | 156 | static 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 | |||
| 166 | static 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 | |||
| 176 | static 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 | |||
| 186 | static 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 | |||
| 196 | static enum xen_irq_type type_from_irq(unsigned irq) | ||
| 197 | { | ||
| 198 | return info_for_irq(irq)->type; | ||
| 199 | } | ||
| 200 | |||
| 201 | static unsigned cpu_from_irq(unsigned irq) | ||
| 202 | { | ||
| 203 | return info_for_irq(irq)->cpu; | ||
| 204 | } | ||
| 205 | |||
| 206 | static 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 | ||
| 122 | static inline unsigned long active_evtchns(unsigned int cpu, | 217 | static 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 | ||
| 146 | static void init_evtchn_cpu_bindings(void) | 241 | static 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 | ||
| 162 | static inline unsigned int cpu_from_evtchn(unsigned int evtchn) | ||
| 163 | { | ||
| 164 | return cpu_evtchn[evtchn]; | ||
| 165 | } | ||
| 166 | |||
| 167 | static inline void clear_evtchn(int port) | 256 | static 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. */ |
