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

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
...@@ -99,25 +99,68 @@ static inline unsigned long get_irqmask(unsigned int irq) ...@@ -99,25 +99,68 @@ static inline unsigned long get_irqmask(unsigned int irq)
return mask; 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) static void leon_unmask_irq(struct irq_data *data)
{ {
unsigned long mask, oldmask, flags; unsigned long mask, oldmask, flags;
int cpu;
mask = (unsigned long)data->chip_data; mask = (unsigned long)data->chip_data;
cpu = irq_choose_cpu(data->affinity);
spin_lock_irqsave(&leon_irq_lock, flags); spin_lock_irqsave(&leon_irq_lock, flags);
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask));
spin_unlock_irqrestore(&leon_irq_lock, flags); spin_unlock_irqrestore(&leon_irq_lock, flags);
} }
static void leon_mask_irq(struct irq_data *data) static void leon_mask_irq(struct irq_data *data)
{ {
unsigned long mask, oldmask, flags; unsigned long mask, oldmask, flags;
int cpu;
mask = (unsigned long)data->chip_data; mask = (unsigned long)data->chip_data;
cpu = irq_choose_cpu(data->affinity);
spin_lock_irqsave(&leon_irq_lock, flags); spin_lock_irqsave(&leon_irq_lock, flags);
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask & ~mask)); LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask));
spin_unlock_irqrestore(&leon_irq_lock, flags); spin_unlock_irqrestore(&leon_irq_lock, flags);
} }
...@@ -144,12 +187,13 @@ static void leon_eoi_irq(struct irq_data *data) ...@@ -144,12 +187,13 @@ static void leon_eoi_irq(struct irq_data *data)
} }
static struct irq_chip leon_irq = { static struct irq_chip leon_irq = {
.name = "leon", .name = "leon",
.irq_startup = leon_startup_irq, .irq_startup = leon_startup_irq,
.irq_shutdown = leon_shutdown_irq, .irq_shutdown = leon_shutdown_irq,
.irq_mask = leon_mask_irq, .irq_mask = leon_mask_irq,
.irq_unmask = leon_unmask_irq, .irq_unmask = leon_unmask_irq,
.irq_eoi = leon_eoi_irq, .irq_eoi = leon_eoi_irq,
.irq_set_affinity = leon_set_affinity,
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment