Loading arch/xtensa/Kconfig +9 −0 Original line number Original line Diff line number Diff line Loading @@ -140,6 +140,15 @@ config NR_CPUS range 2 32 range 2 32 default "4" default "4" config HOTPLUG_CPU bool "Enable CPU hotplug support" depends on SMP help Say Y here to allow turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. Say N if you want to disable CPU hotplug. config MATH_EMULATION config MATH_EMULATION bool "Math emulation" bool "Math emulation" help help Loading arch/xtensa/include/asm/irq.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ static __inline__ int irq_canonicalize(int irq) struct irqaction; struct irqaction; struct irq_domain; struct irq_domain; void migrate_irqs(void); int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, unsigned long int_irq, unsigned long ext_irq, unsigned long int_irq, unsigned long ext_irq, unsigned long *out_hwirq, unsigned int *out_type); unsigned long *out_hwirq, unsigned int *out_type); Loading arch/xtensa/include/asm/smp.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,15 @@ void ipi_init(void); struct seq_file; struct seq_file; void show_ipi_list(struct seq_file *p, int prec); void show_ipi_list(struct seq_file *p, int prec); #ifdef CONFIG_HOTPLUG_CPU void __cpu_die(unsigned int cpu); int __cpu_disable(void); void cpu_die(void); void cpu_restart(void); #endif /* CONFIG_HOTPLUG_CPU */ #endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */ #endif /* _XTENSA_SMP_H */ #endif /* _XTENSA_SMP_H */ arch/xtensa/kernel/head.S +50 −1 Original line number Original line Diff line number Diff line Loading @@ -103,7 +103,7 @@ _SetupMMU: ENDPROC(_start) ENDPROC(_start) __INIT __REF .literal_position .literal_position ENTRY(_startup) ENTRY(_startup) Loading Loading @@ -302,6 +302,55 @@ should_never_return: ENDPROC(_startup) ENDPROC(_startup) #ifdef CONFIG_HOTPLUG_CPU ENTRY(cpu_restart) #if XCHAL_DCACHE_IS_WRITEBACK ___flush_invalidate_dcache_all a2 a3 #else ___invalidate_dcache_all a2 a3 #endif memw movi a2, CCON # MX External Register to Configure Cache movi a3, 0 wer a3, a2 extw rsr a0, prid neg a2, a0 movi a3, cpu_start_id s32i a2, a3, 0 #if XCHAL_DCACHE_IS_WRITEBACK dhwbi a3, 0 #endif 1: l32i a2, a3, 0 dhi a3, 0 bne a2, a0, 1b /* * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow * xt-gdb to single step via DEBUG exceptions received directly * by ocd. */ movi a1, 1 movi a0, 0 wsr a1, windowstart wsr a0, windowbase rsync movi a1, LOCKLEVEL wsr a1, ps rsync j _startup ENDPROC(cpu_restart) #endif /* CONFIG_HOTPLUG_CPU */ /* /* * DATA section * DATA section */ */ Loading arch/xtensa/kernel/irq.c +49 −0 Original line number Original line Diff line number Diff line Loading @@ -153,3 +153,52 @@ void __init init_IRQ(void) #endif #endif variant_init_irq(); variant_init_irq(); } } #ifdef CONFIG_HOTPLUG_CPU static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) { struct irq_desc *desc = irq_to_desc(irq); struct irq_chip *chip = irq_data_get_irq_chip(data); unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); if (chip->irq_set_affinity) chip->irq_set_affinity(data, cpumask_of(cpu), false); raw_spin_unlock_irqrestore(&desc->lock, flags); } /* * The CPU has been marked offline. Migrate IRQs off this CPU. If * the affinity settings do not allow other CPUs, force them onto any * available CPU. */ void migrate_irqs(void) { unsigned int i, cpu = smp_processor_id(); struct irq_desc *desc; for_each_irq_desc(i, desc) { struct irq_data *data = irq_desc_get_irq_data(desc); unsigned int newcpu; if (irqd_is_per_cpu(data)) continue; if (!cpumask_test_cpu(cpu, data->affinity)) continue; newcpu = cpumask_any_and(data->affinity, cpu_online_mask); if (newcpu >= nr_cpu_ids) { pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n", i, cpu); cpumask_setall(data->affinity); newcpu = cpumask_any_and(data->affinity, cpu_online_mask); } route_irq(data, i, newcpu); } } #endif /* CONFIG_HOTPLUG_CPU */ Loading
arch/xtensa/Kconfig +9 −0 Original line number Original line Diff line number Diff line Loading @@ -140,6 +140,15 @@ config NR_CPUS range 2 32 range 2 32 default "4" default "4" config HOTPLUG_CPU bool "Enable CPU hotplug support" depends on SMP help Say Y here to allow turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. Say N if you want to disable CPU hotplug. config MATH_EMULATION config MATH_EMULATION bool "Math emulation" bool "Math emulation" help help Loading
arch/xtensa/include/asm/irq.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ static __inline__ int irq_canonicalize(int irq) struct irqaction; struct irqaction; struct irq_domain; struct irq_domain; void migrate_irqs(void); int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, unsigned long int_irq, unsigned long ext_irq, unsigned long int_irq, unsigned long ext_irq, unsigned long *out_hwirq, unsigned int *out_type); unsigned long *out_hwirq, unsigned int *out_type); Loading
arch/xtensa/include/asm/smp.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,15 @@ void ipi_init(void); struct seq_file; struct seq_file; void show_ipi_list(struct seq_file *p, int prec); void show_ipi_list(struct seq_file *p, int prec); #ifdef CONFIG_HOTPLUG_CPU void __cpu_die(unsigned int cpu); int __cpu_disable(void); void cpu_die(void); void cpu_restart(void); #endif /* CONFIG_HOTPLUG_CPU */ #endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */ #endif /* _XTENSA_SMP_H */ #endif /* _XTENSA_SMP_H */
arch/xtensa/kernel/head.S +50 −1 Original line number Original line Diff line number Diff line Loading @@ -103,7 +103,7 @@ _SetupMMU: ENDPROC(_start) ENDPROC(_start) __INIT __REF .literal_position .literal_position ENTRY(_startup) ENTRY(_startup) Loading Loading @@ -302,6 +302,55 @@ should_never_return: ENDPROC(_startup) ENDPROC(_startup) #ifdef CONFIG_HOTPLUG_CPU ENTRY(cpu_restart) #if XCHAL_DCACHE_IS_WRITEBACK ___flush_invalidate_dcache_all a2 a3 #else ___invalidate_dcache_all a2 a3 #endif memw movi a2, CCON # MX External Register to Configure Cache movi a3, 0 wer a3, a2 extw rsr a0, prid neg a2, a0 movi a3, cpu_start_id s32i a2, a3, 0 #if XCHAL_DCACHE_IS_WRITEBACK dhwbi a3, 0 #endif 1: l32i a2, a3, 0 dhi a3, 0 bne a2, a0, 1b /* * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow * xt-gdb to single step via DEBUG exceptions received directly * by ocd. */ movi a1, 1 movi a0, 0 wsr a1, windowstart wsr a0, windowbase rsync movi a1, LOCKLEVEL wsr a1, ps rsync j _startup ENDPROC(cpu_restart) #endif /* CONFIG_HOTPLUG_CPU */ /* /* * DATA section * DATA section */ */ Loading
arch/xtensa/kernel/irq.c +49 −0 Original line number Original line Diff line number Diff line Loading @@ -153,3 +153,52 @@ void __init init_IRQ(void) #endif #endif variant_init_irq(); variant_init_irq(); } } #ifdef CONFIG_HOTPLUG_CPU static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) { struct irq_desc *desc = irq_to_desc(irq); struct irq_chip *chip = irq_data_get_irq_chip(data); unsigned long flags; raw_spin_lock_irqsave(&desc->lock, flags); if (chip->irq_set_affinity) chip->irq_set_affinity(data, cpumask_of(cpu), false); raw_spin_unlock_irqrestore(&desc->lock, flags); } /* * The CPU has been marked offline. Migrate IRQs off this CPU. If * the affinity settings do not allow other CPUs, force them onto any * available CPU. */ void migrate_irqs(void) { unsigned int i, cpu = smp_processor_id(); struct irq_desc *desc; for_each_irq_desc(i, desc) { struct irq_data *data = irq_desc_get_irq_data(desc); unsigned int newcpu; if (irqd_is_per_cpu(data)) continue; if (!cpumask_test_cpu(cpu, data->affinity)) continue; newcpu = cpumask_any_and(data->affinity, cpu_online_mask); if (newcpu >= nr_cpu_ids) { pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n", i, cpu); cpumask_setall(data->affinity); newcpu = cpumask_any_and(data->affinity, cpu_online_mask); } route_irq(data, i, newcpu); } } #endif /* CONFIG_HOTPLUG_CPU */