genirq: Sanitize irq_set_affinity callbacks
Subsystems (5)
cover genirq: Sanitize irq_set_affinity callbacks
In my last tree wide sweep of irq controller related oddities I discovered that some controllers have an broken implementation versus selecting a single target cpu from the given cpu mask.
The core merily guarantees that at least one of the cpus in the mask is online.
If the controller callback does not restrict the search for a single target to the online cpus it might run into the following situation:
Assume 4 cores online: online mask = 0x0f
Offline Core 1 online mask = 0x0d
Set affinity to 0xe is valid due to online mask 0xd
cpumask_first(0xe) picks core 1, which is offlineThe following series takes care of this. The patches should be tagged stable if there are no objections.
I'm pondering to extend the core functionality to select a target cpu before calling into irq_set_affinity() to prevent future copy and paste failures and get rid of all the duplicated code.
Thanks,
tglx
PATCH 1/5 ia64: Validate online cpus in irq_set_affinity() callbacks
The [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/ia64/kernel/msi_ia64.c | 5 +---- arch/ia64/sn/kernel/irq.c | 4 ++-- arch/ia64/sn/kernel/msi_sn.c | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-)
Index: tip/arch/ia64/kernel/msi_ia64.c =================================--- tip.orig/arch/ia64/kernel/msi_ia64.c +++ tip/arch/ia64/kernel/msi_ia64.c
@@ -17,12 +17,9 @@ static int ia64_set_msi_irq_affinity(str
{
struct msi_msg msg;
u32 addr, data;
- int cpu = first_cpu(*cpu_mask);
+ int cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
unsigned int irq = idata->irq;
- if (!cpu_online(cpu))
- return -1;
-
if (irq_prepare_move(irq, cpu))
return -1;
Index: tip/arch/ia64/sn/kernel/irq.c =================================--- tip.orig/arch/ia64/sn/kernel/irq.c +++ tip/arch/ia64/sn/kernel/irq.c
@@ -209,8 +209,8 @@ static int sn_set_affinity_irq(struct ir
nasid_t nasid;
int slice;
- nasid = cpuid_to_nasid(cpumask_first(mask));
- slice = cpuid_to_slice(cpumask_first(mask));
+ nasid = cpuid_to_nasid(cpumask_first_and(mask, cpu_online_mask));
+ slice = cpuid_to_slice(cpumask_first_and(mask, cpu_online_mask));
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
sn_irq_lh[irq], list)
Index: tip/arch/ia64/sn/kernel/msi_sn.c =================================--- tip.orig/arch/ia64/sn/kernel/msi_sn.c +++ tip/arch/ia64/sn/kernel/msi_sn.c
@@ -166,7 +166,7 @@ static int sn_set_msi_irq_affinity(struc
struct sn_pcibus_provider *provider;
unsigned int cpu, irq = data->irq;
- cpu = cpumask_first(cpu_mask);
+ cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
sn_irq_info = sn_msi_info[irq].sn_irq_info;
if (sn_irq_info = NULL || sn_irq_info->irq_int_bit >= 0)
return -1;
tip-bot for Thomas Gleixner
merge bot[tip:irq/core] ia64: Validate online cpus in irq_set_affinity() callbacks
ia64: Validate online cpus in irq_set_affinity() callbacks
Commit-ID: 785aebd0cfff52e735ad4fd188d3726b5affc8e5 Gitweb: http://git.kernel.org/tip/785aebd0cfff52e735ad4fd188d3726b5affc8e5 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:38 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 12 Mar 2014 13:07:40 +0100
ia64: Validate online cpus in irq_set_affinity() callbacks
The [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/ia64/kernel/msi_ia64.c | 10 ++-------- arch/ia64/sn/kernel/irq.c | 4 ++-- arch/ia64/sn/kernel/msi_sn.c | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-)
arch/ia64/kernel/msi_ia64.c +2 -8
@@ -17,12 +17,9 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata, {struct msi_msg msg;u32 addr, data; -int cpu =first_cpu (*cpu_mask); +int cpu =cpumask_first_and (cpu_mask, cpu_online_mask);unsigned int irq = idata->irq; -if (!cpu_online (cpu)) -return -1 ; -if (irq_prepare_move (irq, cpu))return -1 ;
@@ -139,10 +136,7 @@ static int dmar_msi_set_affinity(struct irq_data *data,unsigned int irq = data->irq;struct irq_cfg *cfg = irq_cfg + irq;struct msi_msg msg; -int cpu =cpumask_first (mask); - -if (!cpu_online (cpu)) -return -1 ; +int cpu =cpumask_first_and (mask, cpu_online_mask);if (irq_prepare_move (irq, cpu))return -1 ;
arch/ia64/sn/kernel/irq.c +2 -2
@@ -209,8 +209,8 @@ static int sn_set_affinity_irq(struct irq_data *data,nasid_t nasid;int slice; - nasid =cpuid_to_nasid (cpumask_first (mask)); - slice =cpuid_to_slice (cpumask_first (mask)); + nasid =cpuid_to_nasid (cpumask_first_and (mask, cpu_online_mask)); + slice =cpuid_to_slice (cpumask_first_and (mask, cpu_online_mask));list_for_each_entry_safe (sn_irq_info, sn_irq_info_safe, sn_irq_lh[irq], list)
arch/ia64/sn/kernel/msi_sn.c +1 -1
@@ -166,7 +166,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,struct sn_pcibus_provider *provider;unsigned int cpu, irq = data->irq; - cpu =cpumask_first (cpu_mask); + cpu =cpumask_first_and (cpu_mask, cpu_online_mask); sn_irq_info = sn_msi_info[irq].sn_irq_info;if (sn_irq_info =NULL || sn_irq_info->irq_int_bit >=0 )return -1 ;
PATCH 2/5 mips: Validate online cpus in irq_set_affinity() callbacks
In reply to Thomas GleixnerThe [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/mips/sibyte/bcm1480/irq.c | 2 +- arch/mips/sibyte/sb1250/irq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/mips/sibyte/bcm1480/irq.c +1 -1
@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct iu64 cur_ints;unsigned long flags; - i =cpumask_first (mask); + i =cpumask_first_and (mask< cpu_online_mask);/* Convert logical CPU to physical CPU */ cpu =cpu_logical_map (i);
arch/mips/sibyte/sb1250/irq.c +1 -1
@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct iru64 cur_ints;unsigned long flags; - i =cpumask_first (mask); + i =cpumask_first_and (mask< cpu_online_mask);/* Convert logical CPU to physical CPU */ cpu =cpu_logical_map (i);
Re: [patch 2/5] mips: Validate online cpus in irq_set_affinity() callbacks
Review
Quoted 2 lines · Thomas Gleixner
(quoted diff) +2
-0+ i = cpumask_first_and(mask< cpu_online_mask); + i = cpumask_first_and(mask< cpu_online_mask);
s/</,/ ?
Re: [patch 2/5] mips: Validate online cpus in irq_set_affinity() callbacks
Quoted 5 lines · Peter Zijlstra
Review
Quoted 2 lines · Thomas Gleixner
(quoted diff) +2
-0+ i = cpumask_first_and(mask< cpu_online_mask); + i = cpumask_first_and(mask< cpu_online_mask);s/</,/ ?
Duh, yes.
tip-bot for Thomas Gleixner
merge bot[tip:irq/core] mips: Validate online cpus in irq_set_affinity() callbacks
In reply to Thomas Gleixnermips: Validate online cpus in irq_set_affinity() callbacks
Commit-ID: 421d1563c6620423d23e394711e3f209e585c161 Gitweb: http://git.kernel.org/tip/421d1563c6620423d23e394711e3f209e585c161 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:39 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 12 Mar 2014 13:07:40 +0100
mips: Validate online cpus in irq_set_affinity() callbacks
The [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/mips/sibyte/bcm1480/irq.c | 2 +- arch/mips/sibyte/sb1250/irq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/mips/sibyte/bcm1480/irq.c +1 -1
@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask,u64 cur_ints;unsigned long flags; - i =cpumask_first (mask); + i =cpumask_first_and (mask, cpu_online_mask);/* Convert logical CPU to physical CPU */ cpu =cpu_logical_map (i);
arch/mips/sibyte/sb1250/irq.c +1 -1
@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,u64 cur_ints;unsigned long flags; - i =cpumask_first (mask); + i =cpumask_first_and (mask, cpu_online_mask);/* Convert logical CPU to physical CPU */ cpu =cpu_logical_map (i);
PATCH 3/5 parisc: Validate online cpus in irq_set_affinity() callbacks
In reply to Thomas GleixnerThe [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/parisc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/parisc/kernel/irq.c +1 -1
@@ -117,7 +117,7 @@ int cpu_check_affinity(struct irq_data *return -EINVAL ;/* whatever mask they set, we just allow one CPU */ - cpu_dest =first_cpu (*dest); + cpu_dest =cpumask_first_and (dest, cpu_online_mask);return cpu_dest; }
tip-bot for Thomas Gleixner
merge bot[tip:irq/core] parisc: Validate online cpus in irq_set_affinity() callbacks
parisc: Validate online cpus in irq_set_affinity() callbacks
Commit-ID: 1ed71e59bca79e866c4bebbe1efc0bc18245119d Gitweb: http://git.kernel.org/tip/1ed71e59bca79e866c4bebbe1efc0bc18245119d Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:40 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 12 Mar 2014 13:07:41 +0100
parisc: Validate online cpus in irq_set_affinity() callbacks
The [user space] interface does not filter out offline cpus. It merily guarantees that the mask contains at least one online cpu.
So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe (is valid due to online mask 0xd) cpumask_first will pick core 1, which is offline
--- arch/parisc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/parisc/kernel/irq.c +1 -1
@@ -117,7 +117,7 @@ int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest)return -EINVAL ;/* whatever mask they set, we just allow one CPU */ - cpu_dest =first_cpu (*dest); + cpu_dest =cpumask_first_and (dest, cpu_online_mask);return cpu_dest; }
PATCH 4/5 xen: Validate online cpus in set_affinity
In reply to Thomas GleixnerThe user space interface does not filter out offline cpus. It merily verifies that the mask contains at least one online cpu. So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe
Selector will pick first set bit, i.e. core 1
--- drivers/xen/events/events_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/xen/events/events_base.c +1 -1
@@ -1324,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irstatic int set_affinity_irq (struct irq_data *data,const struct cpumask *dest,bool force) { -unsigned tcpu =cpumask_first (dest); +unsigned tcpu =cpumask_first_and (dest, cpu_online_mask);return rebind_irq_to_cpu (data->irq, tcpu); }
Re: [patch 4/5] xen: Validate online cpus in set_affinity
Quoted 8 lines · Thomas Gleixner
The user space interface does not filter out offline cpus. It merily verifies that the mask contains at least one online cpu. So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to0xe
Selector will pick first set bit, i.e. core 1
Thanks.
David
Re: [patch 4/5] xen: Validate online cpus in set_affinity
In reply to Thomas GleixnerQuoted 8 lines · Thomas Gleixner
The user space interface does not filter out offline cpus. It merily verifies that the mask contains at least one online cpu. So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to0xe
Selector will pick first set bit, i.e. core 1
Thanks.
David
tip-bot for Thomas Gleixner
merge bot[tip:irq/core] xen: Validate online cpus in set_affinity
In reply to Thomas Gleixnerxen: Validate online cpus in set_affinity
Commit-ID: 753fbd23f5e59ea9dc0cabe0a684d32100a4af02 Gitweb: http://git.kernel.org/tip/753fbd23f5e59ea9dc0cabe0a684d32100a4af02 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:40 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 12 Mar 2014 13:07:41 +0100
xen: Validate online cpus in set_affinity
The user space interface does not filter out offline cpus. It merily verifies that the mask contains at least one online cpu. So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe
Selector will pick first set bit, i.e. core 1
--- drivers/xen/events/events_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/xen/events/events_base.c +1 -1
@@ -1324,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)static int set_affinity_irq (struct irq_data *data,const struct cpumask *dest,bool force) { -unsigned tcpu =cpumask_first (dest); +unsigned tcpu =cpumask_first_and (dest, cpu_online_mask);return rebind_irq_to_cpu (data->irq, tcpu); }
tip-bot for Thomas Gleixner
merge bot[tip:irq/core] xen: Validate online cpus in set_affinity
In reply to Thomas Gleixnerxen: Validate online cpus in set_affinity
Commit-ID: 753fbd23f5e59ea9dc0cabe0a684d32100a4af02 Gitweb: http://git.kernel.org/tip/753fbd23f5e59ea9dc0cabe0a684d32100a4af02 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:40 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 12 Mar 2014 13:07:41 +0100
xen: Validate online cpus in set_affinity
The user space interface does not filter out offline cpus. It merily verifies that the mask contains at least one online cpu. So the selector in the irq chip implementation needs to make sure to pick only an online cpu because otherwise:
Offline Core 1
Set affinity to 0xe
Selector will pick first set bit, i.e. core 1
--- drivers/xen/events/events_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/xen/events/events_base.c +1 -1
@@ -1324,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)static int set_affinity_irq (struct irq_data *data,const struct cpumask *dest,bool force) { -unsigned tcpu =cpumask_first (dest); +unsigned tcpu =cpumask_first_and (dest, cpu_online_mask);return rebind_irq_to_cpu (data->irq, tcpu); }
PATCH 5/5 irqchip: armanda: Sanitize set_irq_affinity()
In reply to Thomas GleixnerThe set_irq_affinity() function has two issues:
1) It has no protection against selecting an offline cpu from the given mask.
2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm.
irq affinity is set to core 3
core 3 goes offline
migration code sets mask to cpu_online_mask and calls the irq_set_affinity() callback of the irq_chip which fails due to bit 0,1,2 set.
So instead of doing silly for_each_cpu() loops just pick any bit of the mask which intersects with the online mask.
The read back of the routing register is pointless as well. We can simply write the new mask as the bits in this register reflect one core.
Get rid of fiddling with the default_irq_affinity as well.
--- drivers/irqchip/irq-armada-370-xp.c | 38 ++++-------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +5 -33
@@ -244,35 +244,16 @@ static DEFINE_RAW_SPINLOCK(irq_controllestatic int armada_xp_set_affinity (struct irq_data *d,const struct cpumask *mask_val,bool force) { -unsigned long reg; -unsigned long new_mask =0 ; -unsigned long online_mask =0 ; -unsigned long count =0 ;irq_hw_number_t hwirq =irqd_to_hwirq (d); +unsigned long mask;int cpu; -for_each_cpu (cpu, mask_val) { - new_mask |=1 <<cpu_logical_map (cpu); - count++; - } - -/* -* Forbid mutlicore interrupt affinity -* This is required since the MPIC HW doesn't limit -* several CPUs from acknowledging the same interrupt. -*/ -if (count >1 ) -return -EINVAL ; - -for_each_cpu (cpu, cpu_online_mask) - online_mask |=1 <<cpu_logical_map (cpu); +/* Select a single core from the affinity mask which is online */ + cpu =cpumask_any_and (mask_val, cpu_online_mask); + mask =1UL <<cpu_logical_map (cpu);raw_spin_lock (&irq_controller_lock); - - reg =readl (main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - reg = (reg & (~online_mask)) | new_mask; -writel (reg, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - +writel (mask, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq));raw_spin_unlock (&irq_controller_lock);return 0 ;
@@ -494,15 +475,6 @@ static int __init armada_370_xp_mpic_of_#ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init (); - -/* -* Set the default affinity from all CPUs to the boot cpu. -* This is required since the MPIC doesn't limit several CPUs -* from acknowledging the same interrupt. -*/ -cpumask_clear (irq_default_affinity); -cpumask_set_cpu (smp_processor_id (), irq_default_affinity); -#endif armada_370_xp_msi_init (node, main_int_res.start);
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Thomas,
nit: s/armanda/armada/ in the patch subject.
Gregory,
Mind providing an Ack on this?
thx,
Jason.
Quoted 100 lines · Thomas Gleixner
The
set_irq_affinity()function has two issues:1) It has no protection against selecting an offline cpu from the given mask.
2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm.
irq affinity is set to core 3
core 3 goes offlinemigration code sets mask to
cpu_online_maskand calls theirq_set_affinity()callback of theirq_chipwhich fails due to bit 0,1,2 set.So instead of doing silly
for_each_cpu()loops just pick any bit of the mask which intersects with the online mask.The read back of the routing register is pointless as well. We can simply write the new mask as the bits in this register reflect one core.
Get rid of fiddling with the
default_irq_affinityas well.Signed-off-by Thomas Gleixner <[email protected]>Cc Gregory CLEMENT <[email protected]>Cc Jason Cooper <[email protected]>--- drivers/irqchip/irq-armada-370-xp.c | 38 ++++-------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-)Index:
tip/drivers/irqchip/irq-armada-370-xp.c
===================================================================drivers/irqchip/irq-armada-370-xp.c +5
-34@@ -244,35 +244,16 @@ static DEFINE_RAW_SPINLOCK(irq_controllestatic int armada_xp_set_affinity (struct irq_data *d,const struct cpumask *mask_val,bool force) { -unsigned long reg; -unsigned long new_mask =0 ; -unsigned long online_mask =0 ; -unsigned long count =0 ;irq_hw_number_t hwirq =irqd_to_hwirq (d); +unsigned long mask;int cpu; -for_each_cpu (cpu, mask_val) { - new_mask |=1 <<cpu_logical_map (cpu); - count++; - } - -/* -* Forbid mutlicore interrupt affinity -* This is required since the MPIC HW doesn't limit -* several CPUs from acknowledging the same interrupt. -*/ -if (count >1 ) -return -EINVAL ; - -for_each_cpu (cpu, cpu_online_mask) - online_mask |=1 <<cpu_logical_map (cpu); +/* Select a single core from the affinity mask which is online */ + cpu =cpumask_any_and (mask_val, cpu_online_mask); + mask =1UL <<cpu_logical_map (cpu);raw_spin_lock (&irq_controller_lock); - - reg =readl (main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - reg = (reg & (~online_mask)) | new_mask; -writel (reg, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - +writel (mask, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq));raw_spin_unlock (&irq_controller_lock);return 0 ;@@ -494,15 +475,6 @@ static int __init armada_370_xp_mpic_of_#ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init (); - -/* -* Set the default affinity from all CPUs to the boot cpu. -* This is required since the MPIC doesn't limit several CPUs -* from acknowledging the same interrupt. -*/ -cpumask_clear (irq_default_affinity); -cpumask_set_cpu (smp_processor_id (), irq_default_affinity); -#endif armada_370_xp_msi_init (node, main_int_res.start); --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Quoted 7 lines · Jason Cooper
Thomas,
nit: s/armanda/armada/ in the patch subject.
Gregory,
Mind providing an Ack on this?
Well sorry but with this patch the kernel doesn't
work anymore.
I am investigating to find if some part could be kept.
Quoted 106 lines
thx,
Jason.
Quoted 100 lines · Thomas Gleixner
The
set_irq_affinity()function has two issues:1) It has no protection against selecting an offline cpu from the given mask.
2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm.
irq affinity is set to core 3
core 3 goes offlinemigration code sets mask to
cpu_online_maskand calls theirq_set_affinity()callback of theirq_chipwhich fails due to bit 0,1,2 set.So instead of doing silly
for_each_cpu()loops just pick any bit of the mask which intersects with the online mask.The read back of the routing register is pointless as well. We can simply write the new mask as the bits in this register reflect one core.
Get rid of fiddling with the
default_irq_affinityas well.Signed-off-by Thomas Gleixner <[email protected]>Cc Gregory CLEMENT <[email protected]>Cc Jason Cooper <[email protected]>--- drivers/irqchip/irq-armada-370-xp.c | 38 ++++-------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-)Index:
tip/drivers/irqchip/irq-armada-370-xp.c
===================================================================drivers/irqchip/irq-armada-370-xp.c +5
-34@@ -244,35 +244,16 @@ static DEFINE_RAW_SPINLOCK(irq_controllestatic int armada_xp_set_affinity (struct irq_data *d,const struct cpumask *mask_val,bool force) { -unsigned long reg; -unsigned long new_mask =0 ; -unsigned long online_mask =0 ; -unsigned long count =0 ;irq_hw_number_t hwirq =irqd_to_hwirq (d); +unsigned long mask;int cpu; -for_each_cpu (cpu, mask_val) { - new_mask |=1 <<cpu_logical_map (cpu); - count++; - } - -/* -* Forbid mutlicore interrupt affinity -* This is required since the MPIC HW doesn't limit -* several CPUs from acknowledging the same interrupt. -*/ -if (count >1 ) -return -EINVAL ; - -for_each_cpu (cpu, cpu_online_mask) - online_mask |=1 <<cpu_logical_map (cpu); +/* Select a single core from the affinity mask which is online */ + cpu =cpumask_any_and (mask_val, cpu_online_mask); + mask =1UL <<cpu_logical_map (cpu);raw_spin_lock (&irq_controller_lock); - - reg =readl (main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - reg = (reg & (~online_mask)) | new_mask; -writel (reg, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - +writel (mask, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq));raw_spin_unlock (&irq_controller_lock);return 0 ;@@ -494,15 +475,6 @@ static int __init armada_370_xp_mpic_of_#ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init (); - -/* -* Set the default affinity from all CPUs to the boot cpu. -* This is required since the MPIC doesn't limit several CPUs -* from acknowledging the same interrupt. -*/ -cpumask_clear (irq_default_affinity); -cpumask_set_cpu (smp_processor_id (), irq_default_affinity); -#endif armada_370_xp_msi_init (node, main_int_res.start); --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Quoted 5 lines · Gregory CLEMENT
Quoted 4 lines · Jason Cooper
Thomas,
nit: s/armanda/armada/ in the patch subject.
Quoted 8 lines
Quoted 3 lines
Gregory,
Mind providing an Ack on this?
Well sorry but with this patch the kernel doesn't
work anymore.I am investigating to find if some part could be kept.
It might be the readback of the routing register. I don't have the datasheet of this.
Thanks,
tglx
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Hi Thomas,
Quoted 11 lines · Thomas Gleixner
Quoted 9 lines · Gregory CLEMENT
Quoted 7 lines · Jason Cooper
Thomas,
nit: s/armanda/armada/ in the patch subject.
Gregory,
Mind providing an Ack on this?
Quoted 7 lines
Quoted 4 lines
Well sorry but with this patch the kernel doesn't
work anymore.I am investigating to find if some part could be kept.
It might be the readback of the routing register. I don't have the datasheet of this.
Sorry for the delay, I was on vacation without the hardware to test it.
Indeed it was the readback of the routing register. (Unfortunately the datasheet was not yet publicly available :( ). In your patch by replacing the line:
writel(mask, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
by the following ones:
reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask; writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
with
#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF
Then it worked.
About masking with the online CPU in the original code, the purpose was to allow sharing the SoC with an other OS by doing AMP. This feature is part of the Marvell version of the kernel.
The idea was to bring this latter in the vanilla kernel, but I am not sure that all the part needed for AMP are acceptable for mainline. So I can add it back later when we will need it.
Thanks,
Gregory
Quoted 5 lines
Thanks,
tglx
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Quoted 21 lines · Gregory CLEMENT
Quoted 2 lines · Thomas Gleixner
It might be the readback of the routing register. I don't have the datasheet of this.
Sorry for the delay, I was on vacation without the hardware to test it.
Indeed it was the readback of the routing register. (Unfortunately the datasheet was not yet publicly available :( ). In your patch by replacing the line:
writel(mask, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));by the following ones:
reg =
readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));with
#defineARMADA_370_XP_INT_SOURCE_CPU_MASK0xF
Quoted 8 lines
Then it worked.
About masking with the online CPU in the original code, the purpose was to allow sharing the SoC with an other OS by doing AMP. This feature is part of the Marvell version of the kernel.
The idea was to bring this latter in the vanilla kernel, but I am not sure that all the part needed for AMP are acceptable for mainline. So I can add it back later when we will need it.
Right.
So are you ok with that patch (including your change) ? If you send me tested/acked-by i'll route it for 3.15
Thanks,
tglx
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Quoted 31 lines · Thomas Gleixner
Quoted 21 lines · Gregory CLEMENT
Quoted 2 lines · Thomas Gleixner
It might be the readback of the routing register. I don't have the datasheet of this.
Sorry for the delay, I was on vacation without the hardware to test it.
Indeed it was the readback of the routing register. (Unfortunately the datasheet was not yet publicly available :( ). In your patch by replacing the line:
writel(mask, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));by the following ones:
reg =
readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));with
#defineARMADA_370_XP_INT_SOURCE_CPU_MASK0xFQuoted 8 lines
Then it worked.
About masking with the online CPU in the original code, the purpose was to allow sharing the SoC with an other OS by doing AMP. This feature is part of the Marvell version of the kernel.
The idea was to bring this latter in the vanilla kernel, but I am not sure that all the part needed for AMP are acceptable for mainline. So I can add it back later when we will need it.
Quoted 4 lines
Right.
So are you ok with that patch (including your change) ? If you send me tested/acked-by i'll route it for 3.15
With the change I included you can add my
Thanks,
Gregory
Quoted 5 lines
Thanks,
tglx
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Hi Thomas,
Quoted 34 lines · Gregory CLEMENT
Quoted 33 lines · Thomas Gleixner
Quoted 21 lines · Gregory CLEMENT
Quoted 2 lines · Thomas Gleixner
It might be the readback of the routing register. I don't have the datasheet of this.
Sorry for the delay, I was on vacation without the hardware to test it.
Indeed it was the readback of the routing register. (Unfortunately the datasheet was not yet publicly available :( ). In your patch by replacing the line:
writel(mask, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));by the following ones:
reg =
readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));with
#defineARMADA_370_XP_INT_SOURCE_CPU_MASK0xFQuoted 8 lines
Then it worked.
About masking with the online CPU in the original code, the purpose was to allow sharing the SoC with an other OS by doing AMP. This feature is part of the Marvell version of the kernel.
The idea was to bring this latter in the vanilla kernel, but I am not sure that all the part needed for AMP are acceptable for mainline. So I can add it back later when we will need it.Right.
Quoted 8 lines
Quoted 2 lines
So are you ok with that patch (including your change) ? If you send me tested/acked-by i'll route it for 3.15
With the change I included you can add my
Acked-by Gregory CLEMENT <[email protected]>Tested-by Gregory CLEMENT <[email protected]>
I have just noticed that this patch was not merged in 3.15. Actually it is not in the core/irq branch of tip.git with the other patches of the same series.
Is there any reason for this?
Thanks,
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Thomas,
Quoted 42 lines · Gregory CLEMENT
Hi Thomas,
Quoted 39 lines · Gregory CLEMENT
Quoted 31 lines · Thomas Gleixner
Quoted 21 lines · Gregory CLEMENT
Quoted 2 lines · Thomas Gleixner
It might be the readback of the routing register. I don't have the datasheet of this.
Sorry for the delay, I was on vacation without the hardware to test it.
Indeed it was the readback of the routing register. (Unfortunately the datasheet was not yet publicly available :( ). In your patch by replacing the line:
writel(mask, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));by the following ones:
reg =
readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));with
#defineARMADA_370_XP_INT_SOURCE_CPU_MASK0xFQuoted 8 lines
Then it worked.
About masking with the online CPU in the original code, the purpose was to allow sharing the SoC with an other OS by doing AMP. This feature is part of the Marvell version of the kernel.
The idea was to bring this latter in the vanilla kernel, but I am not sure that all the part needed for AMP are acceptable for mainline. So I can add it back later when we will need it.Quoted 4 lines
Right.
So are you ok with that patch (including your change) ? If you send me tested/acked-by i'll route it for 3.15
With the change I included you can add my
Quoted 8 lines
Quoted 3 lines
Acked-by Gregory CLEMENT <[email protected]>Tested-by Gregory CLEMENT <[email protected]>I have just noticed that this patch was not merged in 3.15. Actually it is not in the core/irq branch of tip.git with the other patches of the same series.
Is there any reason for this?
I know your mail filters are pretty aggressive and I just wanted to make sure you saw this. I'm also not sure what happened here.
thx,
Jason.
Re: [patch 5/5] irqchip: armanda: Sanitize set_irq_affinity()
Quoted 9 lines · Jason Cooper
Quoted 5 lines · Gregory CLEMENT
I have just noticed that this patch was not merged in 3.15. Actually it is not in the core/irq branch of tip.git with the other patches of the same series.
Is there any reason for this?I know your mail filters are pretty aggressive and I just wanted to make sure you saw this. I'm also not sure what happened here.
Dunno, must have fallen through the cracks. Lemme find it again.
tip-bot for Thomas Gleixner
merge bot[tip:irq/urgent] irqchip: armanda: Sanitize set_irq_affinity()
In reply to Thomas Gleixnerirqchip: armanda: Sanitize set_irq_affinity()
Commit-ID: 8cc3cfc5ccf1680b7c88f874912b6bec2797b76b Gitweb: http://git.kernel.org/tip/8cc3cfc5ccf1680b7c88f874912b6bec2797b76b Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 4 Mar 2014 20:43:41 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Mon, 28 Apr 2014 21:27:15 +0200
irqchip: armanda: Sanitize set_irq_affinity()
The set_irq_affinity() function has two issues:
1) It has no protection against selecting an offline cpu from the given mask.
2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm.
irq affinity is set to core 3
core 3 goes offline
migration code sets mask to cpu_online_mask and calls the irq_set_affinity() callback of the irq_chip which fails due to bit 0,1,2 set.
So instead of doing silly for_each_cpu() loops just pick any bit of the mask which intersects with the online mask.
Get rid of fiddling with the default_irq_affinity as well.
[ Gregory: Fixed the access to the routing register ]
--- drivers/irqchip/irq-armada-370-xp.c | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +6 -31
@@ -41,6 +41,7 @@#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)#define ARMADA_370_XP_INT_SOURCE_CTL (irq) (0x100 + irq*4) +#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)#define ARMADA_375_PPI_CAUSE (0x10)
@@ -244,35 +245,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);static int armada_xp_set_affinity (struct irq_data *d,const struct cpumask *mask_val,bool force) { -unsigned long reg; -unsigned long new_mask =0 ; -unsigned long online_mask =0 ; -unsigned long count =0 ;irq_hw_number_t hwirq =irqd_to_hwirq (d); +unsigned long reg, mask;int cpu; -for_each_cpu (cpu, mask_val) { - new_mask |=1 <<cpu_logical_map (cpu); - count++; - } - -/* -* Forbid mutlicore interrupt affinity -* This is required since the MPIC HW doesn't limit -* several CPUs from acknowledging the same interrupt. -*/ -if (count >1 ) -return -EINVAL ; - -for_each_cpu (cpu, cpu_online_mask) - online_mask |=1 <<cpu_logical_map (cpu); +/* Select a single core from the affinity mask which is online */ + cpu =cpumask_any_and (mask_val, cpu_online_mask); + mask =1UL <<cpu_logical_map (cpu);raw_spin_lock (&irq_controller_lock); - reg =readl (main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); - reg = (reg & (~online_mask)) | new_mask; + reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK )) | mask;writel (reg, main_int_base +ARMADA_370_XP_INT_SOURCE_CTL (hwirq)); -raw_spin_unlock (&irq_controller_lock);return 0 ;
@@ -494,15 +478,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,#ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init (); - -/* -* Set the default affinity from all CPUs to the boot cpu. -* This is required since the MPIC doesn't limit several CPUs -* from acknowledging the same interrupt. -*/ -cpumask_clear (irq_default_affinity); -cpumask_set_cpu (smp_processor_id (), irq_default_affinity); -#endif armada_370_xp_msi_init (node, main_int_res.start);