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>
This commit is contained in:
Родитель
5fcafb7a23
Коммит
01dae0f08d
|
@ -810,27 +810,24 @@ found_version:
|
||||||
got_prop:
|
got_prop:
|
||||||
#ifdef CONFIG_SPARC_LEON
|
#ifdef CONFIG_SPARC_LEON
|
||||||
/* no cpu-type check is needed, it is a SPARC-LEON */
|
/* no cpu-type check is needed, it is a SPARC-LEON */
|
||||||
|
|
||||||
|
sethi %hi(boot_cpu_id), %g2 ! boot-cpu index
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
ba leon_smp_init
|
ldub [%g2 + %lo(boot_cpu_id)], %g1
|
||||||
nop
|
cmp %g1, 0xff ! unset means first CPU
|
||||||
|
bne leon_smp_cpu_startup ! continue only with master
|
||||||
.global leon_smp_init
|
|
||||||
leon_smp_init:
|
|
||||||
/* let boot_cpu_id default to 0 (master always 0) */
|
|
||||||
|
|
||||||
rd %asr17,%g1
|
|
||||||
srl %g1,28,%g1
|
|
||||||
|
|
||||||
cmp %g0,%g1
|
|
||||||
beq sun4c_continue_boot !continue with master
|
|
||||||
nop
|
|
||||||
|
|
||||||
ba leon_smp_cpu_startup
|
|
||||||
nop
|
|
||||||
#else
|
|
||||||
ba sun4c_continue_boot
|
|
||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
|
/* Get CPU-ID from most significant 4-bit of ASR17 */
|
||||||
|
rd %asr17, %g1
|
||||||
|
srl %g1, 28, %g1
|
||||||
|
|
||||||
|
/* Update boot_cpu_id only on boot cpu */
|
||||||
|
stub %g1, [%g2 + %lo(boot_cpu_id)]
|
||||||
|
|
||||||
|
ba sun4c_continue_boot
|
||||||
|
nop
|
||||||
#endif
|
#endif
|
||||||
set cputypval, %o2
|
set cputypval, %o2
|
||||||
ldub [%o2 + 0x4], %l1
|
ldub [%o2 + 0x4], %l1
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
#include "prom.h"
|
#include "prom.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
@ -53,7 +54,7 @@ static inline unsigned int leon_eirq_get(int cpu)
|
||||||
static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
|
static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
unsigned int eirq;
|
unsigned int eirq;
|
||||||
int cpu = hard_smp_processor_id();
|
int cpu = sparc_leon3_cpuid();
|
||||||
|
|
||||||
eirq = leon_eirq_get(cpu);
|
eirq = leon_eirq_get(cpu);
|
||||||
if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
|
if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
|
||||||
|
@ -79,8 +80,8 @@ void leon_eirq_setup(unsigned int eirq)
|
||||||
*/
|
*/
|
||||||
irq_link(veirq);
|
irq_link(veirq);
|
||||||
mask = 1 << eirq;
|
mask = 1 << eirq;
|
||||||
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0));
|
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(boot_cpu_id));
|
||||||
LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask));
|
LEON3_BYPASS_STORE_PA(LEON_IMASK(boot_cpu_id), (oldmask | mask));
|
||||||
sparc_leon_eirq = eirq;
|
sparc_leon_eirq = eirq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,12 +107,12 @@ static int irq_choose_cpu(const struct cpumask *affinity)
|
||||||
|
|
||||||
cpus_and(mask, cpu_online_map, *affinity);
|
cpus_and(mask, cpu_online_map, *affinity);
|
||||||
if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
|
if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
|
||||||
return 0;
|
return boot_cpu_id;
|
||||||
else
|
else
|
||||||
return first_cpu(mask);
|
return first_cpu(mask);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define irq_choose_cpu(affinity) 0
|
#define irq_choose_cpu(affinity) boot_cpu_id
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest,
|
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)
|
||||||
struct device_node *rootnp, *np, *nnp;
|
struct device_node *rootnp, *np, *nnp;
|
||||||
struct property *pp;
|
struct property *pp;
|
||||||
int len;
|
int len;
|
||||||
int cpu, icsel;
|
int icsel;
|
||||||
int ampopts;
|
int ampopts;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -340,9 +341,8 @@ void __init leon_init_timers(irq_handler_t counter_fn)
|
||||||
* accessed anyway.
|
* accessed anyway.
|
||||||
* In AMP systems, Linux must run on CPU0 for the time being.
|
* In AMP systems, Linux must run on CPU0 for the time being.
|
||||||
*/
|
*/
|
||||||
cpu = sparc_leon3_cpuid();
|
icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[boot_cpu_id/8]);
|
||||||
icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
|
icsel = (icsel >> ((7 - (boot_cpu_id&0x7)) * 4)) & 0xf;
|
||||||
icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
|
|
||||||
leon3_irqctrl_regs += icsel;
|
leon3_irqctrl_regs += icsel;
|
||||||
|
|
||||||
/* Probe extended IRQ controller */
|
/* Probe extended IRQ controller */
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
extern ctxd_t *srmmu_ctx_table_phys;
|
extern ctxd_t *srmmu_ctx_table_phys;
|
||||||
static int smp_processors_ready;
|
static int smp_processors_ready;
|
||||||
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
||||||
extern unsigned char boot_cpu_id;
|
|
||||||
extern cpumask_t smp_commenced_mask;
|
extern cpumask_t smp_commenced_mask;
|
||||||
void __init leon_configure_cache_smp(void);
|
void __init leon_configure_cache_smp(void);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче