forked from luck/tmp_suning_uos_patched
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 */
|
/* IRQ <-> IPI mapping */
|
||||||
static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
|
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. */
|
/* Interrupt types. */
|
||||||
struct packed_irq
|
enum xen_irq_type {
|
||||||
{
|
|
||||||
unsigned short evtchn;
|
|
||||||
unsigned char index;
|
|
||||||
unsigned char type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct packed_irq irq_info[NR_IRQS];
|
|
||||||
|
|
||||||
/* Binding types. */
|
|
||||||
enum {
|
|
||||||
IRQT_UNBOUND,
|
IRQT_UNBOUND,
|
||||||
IRQT_PIRQ,
|
IRQT_PIRQ,
|
||||||
IRQT_VIRQ,
|
IRQT_VIRQ,
|
||||||
@ -71,8 +61,34 @@ enum {
|
|||||||
IRQT_EVTCHN
|
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] = {
|
static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
|
||||||
[0 ... NR_EVENT_CHANNELS-1] = -1
|
[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;
|
return cpu_evtchn_mask_p[cpu].bits;
|
||||||
}
|
}
|
||||||
static u8 cpu_evtchn[NR_EVENT_CHANNELS];
|
|
||||||
|
|
||||||
/* Reference counts for bindings to IRQs. */
|
/* Reference counts for bindings to IRQs. */
|
||||||
static int irq_bindcount[NR_IRQS];
|
static int irq_bindcount[NR_IRQS];
|
||||||
@ -96,27 +111,107 @@ static int irq_bindcount[NR_IRQS];
|
|||||||
static struct irq_chip xen_dynamic_chip;
|
static struct irq_chip xen_dynamic_chip;
|
||||||
|
|
||||||
/* Constructor for packed IRQ information. */
|
/* 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.
|
* 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,
|
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));
|
cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
|
||||||
#endif
|
#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));
|
__set_bit(chn, cpu_evtchn_mask(cpu));
|
||||||
|
|
||||||
cpu_evtchn[chn] = cpu;
|
irq_info[irq].cpu = cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_evtchn_cpu_bindings(void)
|
static void init_evtchn_cpu_bindings(void)
|
||||||
@ -155,15 +250,9 @@ static void init_evtchn_cpu_bindings(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
|
|
||||||
memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0)));
|
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)
|
static inline void clear_evtchn(int port)
|
||||||
{
|
{
|
||||||
struct shared_info *s = HYPERVISOR_shared_info;
|
struct shared_info *s = HYPERVISOR_shared_info;
|
||||||
@ -253,6 +342,8 @@ static int find_unbound_irq(void)
|
|||||||
if (WARN_ON(desc == NULL))
|
if (WARN_ON(desc == NULL))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
dynamic_irq_init(irq);
|
||||||
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,12 +358,11 @@ int bind_evtchn_to_irq(unsigned int evtchn)
|
|||||||
if (irq == -1) {
|
if (irq == -1) {
|
||||||
irq = find_unbound_irq();
|
irq = find_unbound_irq();
|
||||||
|
|
||||||
dynamic_irq_init(irq);
|
|
||||||
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
||||||
handle_level_irq, "event");
|
handle_level_irq, "event");
|
||||||
|
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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]++;
|
irq_bindcount[irq]++;
|
||||||
@ -296,7 +386,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
|
|||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
dynamic_irq_init(irq);
|
|
||||||
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
||||||
handle_level_irq, "ipi");
|
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 = bind_ipi.port;
|
||||||
|
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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;
|
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();
|
irq = find_unbound_irq();
|
||||||
|
|
||||||
dynamic_irq_init(irq);
|
|
||||||
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
|
||||||
handle_level_irq, "virq");
|
handle_level_irq, "virq");
|
||||||
|
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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;
|
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)) {
|
switch (type_from_irq(irq)) {
|
||||||
case IRQT_VIRQ:
|
case IRQT_VIRQ:
|
||||||
per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
|
per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
|
||||||
[index_from_irq(irq)] = -1;
|
[virq_from_irq(irq)] = -1;
|
||||||
break;
|
break;
|
||||||
case IRQT_IPI:
|
case IRQT_IPI:
|
||||||
per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
|
per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
|
||||||
[index_from_irq(irq)] = -1;
|
[ipi_from_irq(irq)] = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -389,7 +477,7 @@ static void unbind_from_irq(unsigned int irq)
|
|||||||
bind_evtchn_to_cpu(evtchn, 0);
|
bind_evtchn_to_cpu(evtchn, 0);
|
||||||
|
|
||||||
evtchn_to_irq[evtchn] = -1;
|
evtchn_to_irq[evtchn] = -1;
|
||||||
irq_info[irq] = IRQ_UNBOUND;
|
irq_info[irq] = mk_unbound_info();
|
||||||
|
|
||||||
dynamic_irq_cleanup(irq);
|
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++) {
|
for(i = 0; i < NR_EVENT_CHANNELS; i++) {
|
||||||
if (sync_test_bit(i, sh->evtchn_pending)) {
|
if (sync_test_bit(i, sh->evtchn_pending)) {
|
||||||
printk(" %d: event %d -> irq %d\n",
|
printk(" %d: event %d -> irq %d\n",
|
||||||
cpu_evtchn[i], i,
|
cpu_from_evtchn(i), i,
|
||||||
evtchn_to_irq[i]);
|
evtchn_to_irq[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +694,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
|
|||||||
BUG_ON(irq_bindcount[irq] == 0);
|
BUG_ON(irq_bindcount[irq] == 0);
|
||||||
|
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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);
|
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)
|
if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BUG_ON(irq_info[irq].type != IRQT_VIRQ);
|
BUG_ON(virq_from_irq(irq) != virq);
|
||||||
BUG_ON(irq_info[irq].index != virq);
|
|
||||||
|
|
||||||
/* Get a new binding from Xen. */
|
/* Get a new binding from Xen. */
|
||||||
bind_virq.virq = virq;
|
bind_virq.virq = virq;
|
||||||
@ -729,7 +816,7 @@ static void restore_cpu_virqs(unsigned int cpu)
|
|||||||
|
|
||||||
/* Record the new mapping. */
|
/* Record the new mapping. */
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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);
|
bind_evtchn_to_cpu(evtchn, cpu);
|
||||||
|
|
||||||
/* Ready for use. */
|
/* 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)
|
if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BUG_ON(irq_info[irq].type != IRQT_IPI);
|
BUG_ON(ipi_from_irq(irq) != ipi);
|
||||||
BUG_ON(irq_info[irq].index != ipi);
|
|
||||||
|
|
||||||
/* Get a new binding from Xen. */
|
/* Get a new binding from Xen. */
|
||||||
bind_ipi.vcpu = cpu;
|
bind_ipi.vcpu = cpu;
|
||||||
@ -758,7 +844,7 @@ static void restore_cpu_ipis(unsigned int cpu)
|
|||||||
|
|
||||||
/* Record the new mapping. */
|
/* Record the new mapping. */
|
||||||
evtchn_to_irq[evtchn] = irq;
|
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);
|
bind_evtchn_to_cpu(evtchn, cpu);
|
||||||
|
|
||||||
/* Ready for use. */
|
/* Ready for use. */
|
||||||
|
Loading…
Reference in New Issue
Block a user