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

Commit 93b3238e authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Fix virq decomposition.



The dev_handle and dev_ino fields don't match up exactly to
the traditional IMAP_IGN and IMAP_INO masks.

So store them away in a table and look them up directly.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e83fb17f
Loading
Loading
Loading
Loading
+25 −19
Original line number Original line Diff line number Diff line
@@ -87,7 +87,11 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY
 */
 */
#define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)
#define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)


static unsigned int virt_to_real_irq_table[NR_IRQS];
static struct {
	unsigned int irq;
	unsigned int dev_handle;
	unsigned int dev_ino;
} virt_to_real_irq_table[NR_IRQS];


static unsigned char virt_irq_alloc(unsigned int real_irq)
static unsigned char virt_irq_alloc(unsigned int real_irq)
{
{
@@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq)
	BUILD_BUG_ON(NR_IRQS >= 256);
	BUILD_BUG_ON(NR_IRQS >= 256);


	for (ent = 1; ent < NR_IRQS; ent++) {
	for (ent = 1; ent < NR_IRQS; ent++) {
		if (!virt_to_real_irq_table[ent])
		if (!virt_to_real_irq_table[ent].irq)
			break;
			break;
	}
	}
	if (ent >= NR_IRQS) {
	if (ent >= NR_IRQS) {
@@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq)
		return 0;
		return 0;
	}
	}


	virt_to_real_irq_table[ent] = real_irq;
	virt_to_real_irq_table[ent].irq = real_irq;


	return ent;
	return ent;
}
}
@@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq)
	if (virt_irq >= NR_IRQS)
	if (virt_irq >= NR_IRQS)
		return;
		return;


	real_irq = virt_to_real_irq_table[virt_irq];
	real_irq = virt_to_real_irq_table[virt_irq].irq;
	virt_to_real_irq_table[virt_irq] = 0;
	virt_to_real_irq_table[virt_irq].irq = 0;


	__bucket(real_irq)->virt_irq = 0;
	__bucket(real_irq)->virt_irq = 0;
}
}
@@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq)


static unsigned int virt_to_real_irq(unsigned char virt_irq)
static unsigned int virt_to_real_irq(unsigned char virt_irq)
{
{
	return virt_to_real_irq_table[virt_irq];
	return virt_to_real_irq_table[virt_irq].irq;
}
}


/*
/*
@@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq)
static void sun4v_virq_enable(unsigned int virt_irq)
static void sun4v_virq_enable(unsigned int virt_irq)
{
{
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	unsigned int ino = bucket - &ivector_table[0];


	if (likely(bucket)) {
	if (likely(bucket)) {
		unsigned long cpuid, dev_handle, dev_ino;
		unsigned long cpuid, dev_handle, dev_ino;
@@ -426,8 +429,8 @@ static void sun4v_virq_enable(unsigned int virt_irq)


		cpuid = irq_choose_cpu(virt_irq);
		cpuid = irq_choose_cpu(virt_irq);


		dev_handle = ino & IMAP_IGN;
		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
		dev_ino = ino & IMAP_INO;
		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;


		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
		if (err != HV_EOK)
		if (err != HV_EOK)
@@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq)
static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
{
{
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	unsigned int ino = bucket - &ivector_table[0];


	if (likely(bucket)) {
	if (likely(bucket)) {
		unsigned long cpuid, dev_handle, dev_ino;
		unsigned long cpuid, dev_handle, dev_ino;
@@ -460,8 +462,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)


		cpuid = irq_choose_cpu(virt_irq);
		cpuid = irq_choose_cpu(virt_irq);


		dev_handle = ino & IMAP_IGN;
		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
		dev_ino = ino & IMAP_INO;
		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;


		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
		if (err != HV_EOK)
		if (err != HV_EOK)
@@ -474,14 +476,13 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
static void sun4v_virq_disable(unsigned int virt_irq)
static void sun4v_virq_disable(unsigned int virt_irq)
{
{
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	unsigned int ino = bucket - &ivector_table[0];


	if (likely(bucket)) {
	if (likely(bucket)) {
		unsigned long dev_handle, dev_ino;
		unsigned long dev_handle, dev_ino;
		int err;
		int err;


		dev_handle = ino & IMAP_IGN;
		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
		dev_ino = ino & IMAP_INO;
		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;


		err = sun4v_vintr_set_valid(dev_handle, dev_ino,
		err = sun4v_vintr_set_valid(dev_handle, dev_ino,
					    HV_INTR_DISABLED);
					    HV_INTR_DISABLED);
@@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq)
static void sun4v_virq_end(unsigned int virt_irq)
static void sun4v_virq_end(unsigned int virt_irq)
{
{
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
	unsigned int ino = bucket - &ivector_table[0];
	struct irq_desc *desc = irq_desc + virt_irq;
	struct irq_desc *desc = irq_desc + virt_irq;


	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -505,8 +505,8 @@ static void sun4v_virq_end(unsigned int virt_irq)
		unsigned long dev_handle, dev_ino;
		unsigned long dev_handle, dev_ino;
		int err;
		int err;


		dev_handle = ino & IMAP_IGN;
		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
		dev_ino = ino & IMAP_INO;
		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;


		err = sun4v_vintr_set_state(dev_handle, dev_ino,
		err = sun4v_vintr_set_state(dev_handle, dev_ino,
					    HV_INTR_STATE_IDLE);
					    HV_INTR_STATE_IDLE);
@@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
{
{
	unsigned long sysino, hv_err;
	unsigned long sysino, hv_err;
	unsigned int virq;


	BUG_ON(devhandle & devino);
	BUG_ON(devhandle & devino);


@@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
		prom_halt();
		prom_halt();
	}
	}


	return sun4v_build_common(sysino, &sun4v_virq);
	virq = sun4v_build_common(sysino, &sun4v_virq);

	virt_to_real_irq_table[virq].dev_handle = devhandle;
	virt_to_real_irq_table[virq].dev_ino = devino;

	return virq;
}
}


#ifdef CONFIG_PCI_MSI
#ifdef CONFIG_PCI_MSI