mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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:
parent
792dc4f6cd
commit
ced40d0f3e
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user