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>
This commit is contained in:
Jeremy Fitzhardinge 2009-02-06 14:09:44 -08:00 committed by Ingo Molnar
parent 792dc4f6cd
commit ced40d0f3e
1 changed files with 135 additions and 49 deletions

View File

@ -52,18 +52,8 @@ static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
/* IRQ <-> IPI mapping */
static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
/* Packed IRQ information: binding type, sub-type index, and event channel. */
struct packed_irq
{
unsigned short evtchn;
unsigned char index;
unsigned char type;
};
static struct packed_irq irq_info[NR_IRQS];
/* Binding types. */
enum {
/* Interrupt types. */
enum xen_irq_type {
IRQT_UNBOUND,
IRQT_PIRQ,
IRQT_VIRQ,
@ -71,8 +61,34 @@ enum {
IRQT_EVTCHN
};
/* Convenient shorthand for packed representation of an unbound IRQ. */
#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
/*
* Packed IRQ information:
* type - enum xen_irq_type
* event channel - irq->event channel mapping
* cpu - cpu this event channel is bound to
* index - type-specific information:
* PIRQ - vector, with MSB being "needs EIO"
* VIRQ - virq number
* IPI - IPI vector
* EVTCHN -
*/
struct irq_info
{
enum xen_irq_type type; /* type */
unsigned short evtchn; /* event channel */
unsigned short cpu; /* cpu bound */
union {
unsigned short virq;
enum ipi_vector ipi;
struct {
unsigned short gsi;
unsigned short vector;
} pirq;
} u;
};
static struct irq_info irq_info[NR_IRQS];
static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
[0 ... NR_EVENT_CHANNELS-1] = -1
@ -85,7 +101,6 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
{
return cpu_evtchn_mask_p[cpu].bits;
}
static u8 cpu_evtchn[NR_EVENT_CHANNELS];
/* Reference counts for bindings to IRQs. */
static int irq_bindcount[NR_IRQS];
@ -96,27 +111,107 @@ static int irq_bindcount[NR_IRQS];
static struct irq_chip xen_dynamic_chip;
/* Constructor for packed IRQ information. */
static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
static struct irq_info mk_unbound_info(void)
{
return (struct packed_irq) { evtchn, index, type };
return (struct irq_info) { .type = IRQT_UNBOUND };
}
static struct irq_info mk_evtchn_info(unsigned short evtchn)
{
return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn };
}
static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi)
{
return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn,
.u.ipi = ipi };
}
static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq)
{
return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn,
.u.virq = virq };
}
static struct irq_info mk_pirq_info(unsigned short evtchn,
unsigned short gsi, unsigned short vector)
{
return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
.u.pirq = { .gsi = gsi, .vector = vector } };
}
/*
* Accessors for packed IRQ information.
*/
static inline unsigned int evtchn_from_irq(int irq)
static struct irq_info *info_for_irq(unsigned irq)
{
return irq_info[irq].evtchn;
return &irq_info[irq];
}
static inline unsigned int index_from_irq(int irq)
static unsigned int evtchn_from_irq(unsigned irq)
{
return irq_info[irq].index;
return info_for_irq(irq)->evtchn;
}
static inline unsigned int type_from_irq(int irq)
static enum ipi_vector ipi_from_irq(unsigned irq)
{
return irq_info[irq].type;
struct irq_info *info = info_for_irq(irq);
BUG_ON(info == NULL);
BUG_ON(info->type != IRQT_IPI);
return info->u.ipi;
}
static unsigned virq_from_irq(unsigned irq)
{
struct irq_info *info = info_for_irq(irq);
BUG_ON(info == NULL);
BUG_ON(info->type != IRQT_VIRQ);
return info->u.virq;
}
static unsigned gsi_from_irq(unsigned irq)
{
struct irq_info *info = info_for_irq(irq);
BUG_ON(info == NULL);
BUG_ON(info->type != IRQT_PIRQ);
return info->u.pirq.gsi;
}
static unsigned vector_from_irq(unsigned irq)
{
struct irq_info *info = info_for_irq(irq);
BUG_ON(info == NULL);
BUG_ON(info->type != IRQT_PIRQ);
return info->u.pirq.vector;
}
static enum xen_irq_type type_from_irq(unsigned irq)
{
return info_for_irq(irq)->type;
}
static unsigned cpu_from_irq(unsigned irq)
{
return info_for_irq(irq)->cpu;
}
static unsigned int cpu_from_evtchn(unsigned int evtchn)
{
int irq = evtchn_to_irq[evtchn];
unsigned ret = 0;
if (irq != -1)
ret = cpu_from_irq(irq);
return ret;
}
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)
cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
#endif
__clear_bit(chn, cpu_evtchn_mask(cpu_evtchn[chn]));
__clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
__set_bit(chn, cpu_evtchn_mask(cpu));
cpu_evtchn[chn] = cpu;
irq_info[irq].cpu = cpu;
}
static void init_evtchn_cpu_bindings(void)
@ -155,15 +250,9 @@ static void init_evtchn_cpu_bindings(void)
}
#endif
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0)));
}
static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
{
return cpu_evtchn[evtchn];
}
static inline void clear_evtchn(int port)
{
struct shared_info *s = HYPERVISOR_shared_info;
@ -253,6 +342,8 @@ static int find_unbound_irq(void)
if (WARN_ON(desc == NULL))
return -1;
dynamic_irq_init(irq);
return irq;
}
@ -267,12 +358,11 @@ int bind_evtchn_to_irq(unsigned int evtchn)
if (irq == -1) {
irq = find_unbound_irq();
dynamic_irq_init(irq);
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "event");
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
irq_info[irq] = mk_evtchn_info(evtchn);
}
irq_bindcount[irq]++;
@ -296,7 +386,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
if (irq < 0)
goto out;
dynamic_irq_init(irq);
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "ipi");
@ -307,7 +396,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
evtchn = bind_ipi.port;
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
irq_info[irq] = mk_ipi_info(evtchn, ipi);
per_cpu(ipi_to_irq, cpu)[ipi] = irq;
@ -341,12 +430,11 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
irq = find_unbound_irq();
dynamic_irq_init(irq);
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "virq");
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
irq_info[irq] = mk_virq_info(evtchn, virq);
per_cpu(virq_to_irq, cpu)[virq] = irq;
@ -375,11 +463,11 @@ static void unbind_from_irq(unsigned int irq)
switch (type_from_irq(irq)) {
case IRQT_VIRQ:
per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
[index_from_irq(irq)] = -1;
[virq_from_irq(irq)] = -1;
break;
case IRQT_IPI:
per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
[index_from_irq(irq)] = -1;
[ipi_from_irq(irq)] = -1;
break;
default:
break;
@ -389,7 +477,7 @@ static void unbind_from_irq(unsigned int irq)
bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = -1;
irq_info[irq] = IRQ_UNBOUND;
irq_info[irq] = mk_unbound_info();
dynamic_irq_cleanup(irq);
}
@ -507,8 +595,8 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
for(i = 0; i < NR_EVENT_CHANNELS; i++) {
if (sync_test_bit(i, sh->evtchn_pending)) {
printk(" %d: event %d -> irq %d\n",
cpu_evtchn[i], i,
evtchn_to_irq[i]);
cpu_from_evtchn(i), i,
evtchn_to_irq[i]);
}
}
@ -606,7 +694,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
BUG_ON(irq_bindcount[irq] == 0);
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
irq_info[irq] = mk_evtchn_info(evtchn);
spin_unlock(&irq_mapping_update_lock);
@ -716,8 +804,7 @@ static void restore_cpu_virqs(unsigned int cpu)
if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
continue;
BUG_ON(irq_info[irq].type != IRQT_VIRQ);
BUG_ON(irq_info[irq].index != virq);
BUG_ON(virq_from_irq(irq) != virq);
/* Get a new binding from Xen. */
bind_virq.virq = virq;
@ -729,7 +816,7 @@ static void restore_cpu_virqs(unsigned int cpu)
/* Record the new mapping. */
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
irq_info[irq] = mk_virq_info(evtchn, virq);
bind_evtchn_to_cpu(evtchn, cpu);
/* Ready for use. */
@ -746,8 +833,7 @@ static void restore_cpu_ipis(unsigned int cpu)
if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
continue;
BUG_ON(irq_info[irq].type != IRQT_IPI);
BUG_ON(irq_info[irq].index != ipi);
BUG_ON(ipi_from_irq(irq) != ipi);
/* Get a new binding from Xen. */
bind_ipi.vcpu = cpu;
@ -758,7 +844,7 @@ static void restore_cpu_ipis(unsigned int cpu)
/* Record the new mapping. */
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
irq_info[irq] = mk_ipi_info(evtchn, ipi);
bind_evtchn_to_cpu(evtchn, cpu);
/* Ready for use. */