Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ced40d0f authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Ingo Molnar
Browse files

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: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 792dc4f6
Loading
Loading
Loading
Loading
+135 −49
Original line number Diff line number Diff line
@@ -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];
}

static unsigned int evtchn_from_irq(unsigned irq)
{
	return irq_info[irq].evtchn;
	return info_for_irq(irq)->evtchn;
}

static inline unsigned int index_from_irq(int irq)
static enum ipi_vector ipi_from_irq(unsigned irq)
{
	return irq_info[irq].index;
	struct irq_info *info = info_for_irq(irq);

	BUG_ON(info == NULL);
	BUG_ON(info->type != IRQT_IPI);

	return info->u.ipi;
}

static inline unsigned int type_from_irq(int irq)
static unsigned virq_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_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,7 +595,7 @@ 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,
			       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. */