* [PATCH 7/7] sparc32,leon: implement genirq CPU affinity
@ 2011-04-19 16:07 Daniel Hellstrom
2011-04-19 19:27 ` Sam Ravnborg
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Daniel Hellstrom @ 2011-04-19 16:07 UTC (permalink / raw)
To: sparclinux
A simple implementation of CPU affinity, the first CPU in
the affinity CPU mask always takes the IRQ.
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
arch/sparc/kernel/leon_kernel.c | 66 +++++++++++++++++++++++++++++++++------
1 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 26acc75..e12f4e8 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -100,25 +100,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 leon3_boot_cpu;
+ else
+ return first_cpu(mask);
+}
+
+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;
+}
+#else
+#define irq_choose_cpu(affinity) leon3_boot_cpu
+#endif
+
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(leon3_boot_cpu));
- LEON3_BYPASS_STORE_PA(LEON_IMASK(leon3_boot_cpu), (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(leon3_boot_cpu));
- LEON3_BYPASS_STORE_PA(LEON_IMASK(leon3_boot_cpu), (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);
}
@@ -145,12 +188,15 @@ static void leon_eoi_irq(struct irq_data *data)
}
static struct irq_chip leon_irq = {
- .name = "leon",
- .irq_startup = leon_startup_irq,
- .irq_shutdown = leon_shutdown_irq,
- .irq_mask = leon_mask_irq,
- .irq_unmask = leon_unmask_irq,
- .irq_eoi = leon_eoi_irq,
+ .name = "leon",
+ .irq_startup = leon_startup_irq,
+ .irq_shutdown = leon_shutdown_irq,
+ .irq_mask = leon_mask_irq,
+ .irq_unmask = leon_unmask_irq,
+ .irq_eoi = leon_eoi_irq,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = leon_set_affinity,
+#endif
};
/*
--
1.5.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 7/7] sparc32,leon: implement genirq CPU affinity
2011-04-19 16:07 [PATCH 7/7] sparc32,leon: implement genirq CPU affinity Daniel Hellstrom
@ 2011-04-19 19:27 ` Sam Ravnborg
2011-04-20 7:20 ` Daniel Hellstrom
2011-04-20 7:34 ` Daniel Hellstrom
2 siblings, 0 replies; 4+ messages in thread
From: Sam Ravnborg @ 2011-04-19 19:27 UTC (permalink / raw)
To: sparclinux
On Tue, Apr 19, 2011 at 06:07:19PM +0200, Daniel Hellstrom wrote:
> A simple implementation of CPU affinity, the first CPU in
> the affinity CPU mask always takes the IRQ.
>
> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
> ---
> arch/sparc/kernel/leon_kernel.c | 66 +++++++++++++++++++++++++++++++++------
> 1 files changed, 56 insertions(+), 10 deletions(-)
>
> diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
> index 26acc75..e12f4e8 100644
> --- a/arch/sparc/kernel/leon_kernel.c
> +++ b/arch/sparc/kernel/leon_kernel.c
> @@ -100,25 +100,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 leon3_boot_cpu;
> + else
> + return first_cpu(mask);
> +}
> +
> +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;
> +}
> +#else
> +#define irq_choose_cpu(affinity) leon3_boot_cpu
> +#endif
We could always define the leon_set_affinity() function
to avoid ifdeffery in irq_chip definition.
The expense is that we define this function in both the
UP and SMP case - it is NOT called by the generic irq
layer in the UP case.
Sam
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 7/7] sparc32,leon: implement genirq CPU affinity
2011-04-19 16:07 [PATCH 7/7] sparc32,leon: implement genirq CPU affinity Daniel Hellstrom
2011-04-19 19:27 ` Sam Ravnborg
@ 2011-04-20 7:20 ` Daniel Hellstrom
2011-04-20 7:34 ` Daniel Hellstrom
2 siblings, 0 replies; 4+ messages in thread
From: Daniel Hellstrom @ 2011-04-20 7:20 UTC (permalink / raw)
To: sparclinux
Sam Ravnborg wrote:
>On Tue, Apr 19, 2011 at 06:07:19PM +0200, Daniel Hellstrom wrote:
>
>
>>A simple implementation of CPU affinity, the first CPU in
>>the affinity CPU mask always takes the IRQ.
>>
>>Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>>---
>> arch/sparc/kernel/leon_kernel.c | 66 +++++++++++++++++++++++++++++++++------
>> 1 files changed, 56 insertions(+), 10 deletions(-)
>>
>>diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
>>index 26acc75..e12f4e8 100644
>>--- a/arch/sparc/kernel/leon_kernel.c
>>+++ b/arch/sparc/kernel/leon_kernel.c
>>@@ -100,25 +100,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 leon3_boot_cpu;
>>+ else
>>+ return first_cpu(mask);
>>+}
>>+
>>+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;
>>+}
>>+#else
>>+#define irq_choose_cpu(affinity) leon3_boot_cpu
>>+#endif
>>
>>
>
>We could always define the leon_set_affinity() function
>to avoid ifdeffery in irq_chip definition.
>
>
Yes, that is what sparc64 does.
>The expense is that we define this function in both the
>UP and SMP case - it is NOT called by the generic irq
>layer in the UP case.
>
>
Yes, it would increase the footprint to remove one ifdef. I could add a
"#define leon_set_affinity NULL" in the already present ifdef above to
avoid the extra ifdef in chip declaration?
Thanks,
Daniel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 7/7] sparc32,leon: implement genirq CPU affinity
2011-04-19 16:07 [PATCH 7/7] sparc32,leon: implement genirq CPU affinity Daniel Hellstrom
2011-04-19 19:27 ` Sam Ravnborg
2011-04-20 7:20 ` Daniel Hellstrom
@ 2011-04-20 7:34 ` Daniel Hellstrom
2 siblings, 0 replies; 4+ messages in thread
From: Daniel Hellstrom @ 2011-04-20 7:34 UTC (permalink / raw)
To: sparclinux
Daniel Hellstrom wrote:
> Sam Ravnborg wrote:
>
>> On Tue, Apr 19, 2011 at 06:07:19PM +0200, Daniel Hellstrom wrote:
>>
>>
>>> A simple implementation of CPU affinity, the first CPU in
>>> the affinity CPU mask always takes the IRQ.
>>>
>>> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>>> ---
>>> arch/sparc/kernel/leon_kernel.c | 66
>>> +++++++++++++++++++++++++++++++++------
>>> 1 files changed, 56 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/arch/sparc/kernel/leon_kernel.c
>>> b/arch/sparc/kernel/leon_kernel.c
>>> index 26acc75..e12f4e8 100644
>>> --- a/arch/sparc/kernel/leon_kernel.c
>>> +++ b/arch/sparc/kernel/leon_kernel.c
>>> @@ -100,25 +100,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 leon3_boot_cpu;
>>> + else
>>> + return first_cpu(mask);
>>> +}
>>> +
>>> +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;
>>> +}
>>> +#else
>>> +#define irq_choose_cpu(affinity) leon3_boot_cpu
>>> +#endif
>>>
>>
>>
>> We could always define the leon_set_affinity() function
>> to avoid ifdeffery in irq_chip definition.
>>
>>
> Yes, that is what sparc64 does.
>
>> The expense is that we define this function in both the
>> UP and SMP case - it is NOT called by the generic irq
>> layer in the UP case.
>>
>>
> Yes, it would increase the footprint to remove one ifdef. I could add
> a "#define leon_set_affinity NULL" in the already present ifdef above
> to avoid the extra ifdef in chip declaration?
Due to compiler optimizations the function is reduced to two
instructions anyway, I go with your and the sparc64 way. I will resend
the patch with your acked-by line as well.
00000034 <leon_set_affinity>:
34: 81 c3 e0 08 retl
38: 90 10 20 00 clr %o0
Thanks,
Daniel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-04-20 7:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-19 16:07 [PATCH 7/7] sparc32,leon: implement genirq CPU affinity Daniel Hellstrom
2011-04-19 19:27 ` Sam Ravnborg
2011-04-20 7:20 ` Daniel Hellstrom
2011-04-20 7:34 ` Daniel Hellstrom
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.