diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-04-21 00:20:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-21 19:44:45 -0400 |
commit | 01dae0f08dddf6ba86f956e60dceee4968f7a555 (patch) | |
tree | 5bf21fbff042da53d691ca834599dd7cde164669 /arch/sparc | |
parent | 5fcafb7a23e35b2f1a5243f4dd536240f52c8ceb (diff) |
sparc32,leon: operate on boot-cpu IRQ controller registers
* proper initialization of boot_cpu_id (no hardcoding to 0)
* use boot_cpu_id index to address into the IRQ controller where
appropriate
Each CPU has a separate set of IRQ controller registers, this
patch makes sure that the boot-cpu registers are used instead
of CPU0's.
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/head_32.S | 27 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 18 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_smp.c | 1 |
3 files changed, 21 insertions, 25 deletions
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 520c615d3766..587785759838 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S | |||
@@ -810,28 +810,25 @@ found_version: | |||
810 | got_prop: | 810 | got_prop: |
811 | #ifdef CONFIG_SPARC_LEON | 811 | #ifdef CONFIG_SPARC_LEON |
812 | /* no cpu-type check is needed, it is a SPARC-LEON */ | 812 | /* no cpu-type check is needed, it is a SPARC-LEON */ |
813 | #ifdef CONFIG_SMP | ||
814 | ba leon_smp_init | ||
815 | nop | ||
816 | 813 | ||
817 | .global leon_smp_init | 814 | sethi %hi(boot_cpu_id), %g2 ! boot-cpu index |
818 | leon_smp_init: | ||
819 | /* let boot_cpu_id default to 0 (master always 0) */ | ||
820 | 815 | ||
821 | rd %asr17,%g1 | 816 | #ifdef CONFIG_SMP |
822 | srl %g1,28,%g1 | 817 | ldub [%g2 + %lo(boot_cpu_id)], %g1 |
818 | cmp %g1, 0xff ! unset means first CPU | ||
819 | bne leon_smp_cpu_startup ! continue only with master | ||
820 | nop | ||
821 | #endif | ||
822 | /* Get CPU-ID from most significant 4-bit of ASR17 */ | ||
823 | rd %asr17, %g1 | ||
824 | srl %g1, 28, %g1 | ||
823 | 825 | ||
824 | cmp %g0,%g1 | 826 | /* Update boot_cpu_id only on boot cpu */ |
825 | beq sun4c_continue_boot !continue with master | 827 | stub %g1, [%g2 + %lo(boot_cpu_id)] |
826 | nop | ||
827 | 828 | ||
828 | ba leon_smp_cpu_startup | ||
829 | nop | ||
830 | #else | ||
831 | ba sun4c_continue_boot | 829 | ba sun4c_continue_boot |
832 | nop | 830 | nop |
833 | #endif | 831 | #endif |
834 | #endif | ||
835 | set cputypval, %o2 | 832 | set cputypval, %o2 |
836 | ldub [%o2 + 0x4], %l1 | 833 | ldub [%o2 + 0x4], %l1 |
837 | 834 | ||
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index ab1458454422..8417a914e8a3 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/traps.h> | 20 | #include <asm/traps.h> |
21 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
22 | #include <asm/smp.h> | 22 | #include <asm/smp.h> |
23 | #include <asm/setup.h> | ||
23 | 24 | ||
24 | #include "prom.h" | 25 | #include "prom.h" |
25 | #include "irq.h" | 26 | #include "irq.h" |
@@ -53,7 +54,7 @@ static inline unsigned int leon_eirq_get(int cpu) | |||
53 | static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc) | 54 | static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc) |
54 | { | 55 | { |
55 | unsigned int eirq; | 56 | unsigned int eirq; |
56 | int cpu = hard_smp_processor_id(); | 57 | int cpu = sparc_leon3_cpuid(); |
57 | 58 | ||
58 | eirq = leon_eirq_get(cpu); | 59 | eirq = leon_eirq_get(cpu); |
59 | if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ | 60 | if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ |
@@ -79,8 +80,8 @@ void leon_eirq_setup(unsigned int eirq) | |||
79 | */ | 80 | */ |
80 | irq_link(veirq); | 81 | irq_link(veirq); |
81 | mask = 1 << eirq; | 82 | mask = 1 << eirq; |
82 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); | 83 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(boot_cpu_id)); |
83 | LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); | 84 | LEON3_BYPASS_STORE_PA(LEON_IMASK(boot_cpu_id), (oldmask | mask)); |
84 | sparc_leon_eirq = eirq; | 85 | sparc_leon_eirq = eirq; |
85 | } | 86 | } |
86 | 87 | ||
@@ -106,12 +107,12 @@ static int irq_choose_cpu(const struct cpumask *affinity) | |||
106 | 107 | ||
107 | cpus_and(mask, cpu_online_map, *affinity); | 108 | cpus_and(mask, cpu_online_map, *affinity); |
108 | if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) | 109 | if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) |
109 | return 0; | 110 | return boot_cpu_id; |
110 | else | 111 | else |
111 | return first_cpu(mask); | 112 | return first_cpu(mask); |
112 | } | 113 | } |
113 | #else | 114 | #else |
114 | #define irq_choose_cpu(affinity) 0 | 115 | #define irq_choose_cpu(affinity) boot_cpu_id |
115 | #endif | 116 | #endif |
116 | 117 | ||
117 | static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest, | 118 | static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest, |
@@ -241,7 +242,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
241 | struct device_node *rootnp, *np, *nnp; | 242 | struct device_node *rootnp, *np, *nnp; |
242 | struct property *pp; | 243 | struct property *pp; |
243 | int len; | 244 | int len; |
244 | int cpu, icsel; | 245 | int icsel; |
245 | int ampopts; | 246 | int ampopts; |
246 | int err; | 247 | int err; |
247 | 248 | ||
@@ -340,9 +341,8 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
340 | * accessed anyway. | 341 | * accessed anyway. |
341 | * In AMP systems, Linux must run on CPU0 for the time being. | 342 | * In AMP systems, Linux must run on CPU0 for the time being. |
342 | */ | 343 | */ |
343 | cpu = sparc_leon3_cpuid(); | 344 | icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[boot_cpu_id/8]); |
344 | icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); | 345 | icsel = (icsel >> ((7 - (boot_cpu_id&0x7)) * 4)) & 0xf; |
345 | icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; | ||
346 | leon3_irqctrl_regs += icsel; | 346 | leon3_irqctrl_regs += icsel; |
347 | 347 | ||
348 | /* Probe extended IRQ controller */ | 348 | /* Probe extended IRQ controller */ |
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index b4059dbb6d93..cbd8e31d01ff 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
@@ -50,7 +50,6 @@ | |||
50 | extern ctxd_t *srmmu_ctx_table_phys; | 50 | extern ctxd_t *srmmu_ctx_table_phys; |
51 | static int smp_processors_ready; | 51 | static int smp_processors_ready; |
52 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | 52 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; |
53 | extern unsigned char boot_cpu_id; | ||
54 | extern cpumask_t smp_commenced_mask; | 53 | extern cpumask_t smp_commenced_mask; |
55 | void __init leon_configure_cache_smp(void); | 54 | void __init leon_configure_cache_smp(void); |
56 | 55 | ||