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

Commit 5eb1f4fc authored by Daniel Hellstrom's avatar Daniel Hellstrom Committed by David S. Miller
Browse files

sparc32,leon: implement genirq CPU affinity



A simple implementation of CPU affinity, the first CPU in
the affinity CPU mask always takes the IRQ.

Signed-off-by: default avatarDaniel Hellstrom <daniel@gaisler.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a481b5d0
Loading
Loading
Loading
Loading
+54 −10
Original line number Diff line number Diff line
@@ -99,25 +99,68 @@ static inline unsigned long get_irqmask(unsigned int irq)
	return mask;
}

#ifdef CONFIG_SMP
static int irq_choose_cpu(const struct cpumask *affinity)
{
	cpumask_t mask;

	cpus_and(mask, cpu_online_map, *affinity);
	if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
		return 0;
	else
		return first_cpu(mask);
}
#else
#define irq_choose_cpu(affinity) 0
#endif

static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest,
			     bool force)
{
	unsigned long mask, oldmask, flags;
	int oldcpu, newcpu;

	mask = (unsigned long)data->chip_data;
	oldcpu = irq_choose_cpu(data->affinity);
	newcpu = irq_choose_cpu(dest);

	if (oldcpu == newcpu)
		goto out;

	/* unmask on old CPU first before enabling on the selected CPU */
	spin_lock_irqsave(&leon_irq_lock, flags);
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask));
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask));
	spin_unlock_irqrestore(&leon_irq_lock, flags);
out:
	return IRQ_SET_MASK_OK;
}

static void leon_unmask_irq(struct irq_data *data)
{
	unsigned long mask, oldmask, flags;
	int cpu;

	mask = (unsigned long)data->chip_data;
	cpu = irq_choose_cpu(data->affinity);
	spin_lock_irqsave(&leon_irq_lock, flags);
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask));
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask));
	spin_unlock_irqrestore(&leon_irq_lock, flags);
}

static void leon_mask_irq(struct irq_data *data)
{
	unsigned long mask, oldmask, flags;
	int cpu;

	mask = (unsigned long)data->chip_data;
	cpu = irq_choose_cpu(data->affinity);
	spin_lock_irqsave(&leon_irq_lock, flags);
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask & ~mask));
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask));
	spin_unlock_irqrestore(&leon_irq_lock, flags);
}

@@ -150,6 +193,7 @@ static struct irq_chip leon_irq = {
	.irq_mask		= leon_mask_irq,
	.irq_unmask		= leon_unmask_irq,
	.irq_eoi		= leon_eoi_irq,
	.irq_set_affinity	= leon_set_affinity,
};

/*