Commit 53124cd3 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.ninka.net:/home/davem/src/BK/sparc-2.5

into kernel.bkbits.net:/home/davem/sparc-2.5
parents 76e8b3a4 0c588692
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/fpumacro.h> #include <asm/fpumacro.h>
#include <asm/cpudata.h>
DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
struct cpu_iu_info { struct cpu_iu_info {
short manuf; short manuf;
...@@ -52,18 +55,16 @@ struct cpu_iu_info linux_sparc_chips[] = { ...@@ -52,18 +55,16 @@ struct cpu_iu_info linux_sparc_chips[] = {
#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
char *sparc_cpu_type[NR_CPUS] = { "cpu-oops", }; char *sparc_cpu_type = "cpu-oops";
char *sparc_fpu_type[NR_CPUS] = { "fpu-oops", }; char *sparc_fpu_type = "fpu-oops";
unsigned int fsr_storage; unsigned int fsr_storage;
void __init cpu_probe(void) void __init cpu_probe(void)
{ {
unsigned long ver, fpu_vers, manuf, impl, fprs; unsigned long ver, fpu_vers, manuf, impl, fprs;
int i, cpuid; int i;
cpuid = hard_smp_processor_id();
fprs = fprs_read(); fprs = fprs_read();
fprs_write(FPRS_FEF); fprs_write(FPRS_FEF);
__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]"
...@@ -80,7 +81,7 @@ void __init cpu_probe(void) ...@@ -80,7 +81,7 @@ void __init cpu_probe(void)
for (i = 0; i < NSPARCCHIPS; i++) { for (i = 0; i < NSPARCCHIPS; i++) {
if (linux_sparc_chips[i].manuf == manuf) { if (linux_sparc_chips[i].manuf == manuf) {
if (linux_sparc_chips[i].impl == impl) { if (linux_sparc_chips[i].impl == impl) {
sparc_cpu_type[cpuid] = sparc_cpu_type =
linux_sparc_chips[i].cpu_name; linux_sparc_chips[i].cpu_name;
break; break;
} }
...@@ -99,14 +100,14 @@ void __init cpu_probe(void) ...@@ -99,14 +100,14 @@ void __init cpu_probe(void)
printk("DEBUG: manuf[%lx] impl[%lx]\n", printk("DEBUG: manuf[%lx] impl[%lx]\n",
manuf, impl); manuf, impl);
} }
sparc_cpu_type[cpuid] = "Unknown CPU"; sparc_cpu_type = "Unknown CPU";
} }
for (i = 0; i < NSPARCFPU; i++) { for (i = 0; i < NSPARCFPU; i++) {
if (linux_sparc_fpu[i].manuf == manuf && if (linux_sparc_fpu[i].manuf == manuf &&
linux_sparc_fpu[i].impl == impl) { linux_sparc_fpu[i].impl == impl) {
if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { if (linux_sparc_fpu[i].fpu_vers == fpu_vers) {
sparc_fpu_type[cpuid] = sparc_fpu_type =
linux_sparc_fpu[i].fp_name; linux_sparc_fpu[i].fp_name;
break; break;
} }
...@@ -116,6 +117,6 @@ void __init cpu_probe(void) ...@@ -116,6 +117,6 @@ void __init cpu_probe(void)
if (i == NSPARCFPU) { if (i == NSPARCFPU) {
printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n",
manuf, impl, fpu_vers); manuf, impl, fpu_vers);
sparc_fpu_type[cpuid] = "Unknown FPU"; sparc_fpu_type = "Unknown FPU";
} }
} }
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/errno.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/oplib.h> #include <asm/oplib.h>
...@@ -18,79 +19,122 @@ ...@@ -18,79 +19,122 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/cpudata.h>
/* Used to synchronize acceses to NatSemi SUPER I/O chip configure /* Used to synchronize acceses to NatSemi SUPER I/O chip configure
* operations in asm/ns87303.h * operations in asm/ns87303.h
*/ */
spinlock_t ns87303_lock = SPIN_LOCK_UNLOCKED; spinlock_t ns87303_lock = SPIN_LOCK_UNLOCKED;
struct prom_cpuinfo linux_cpus[NR_CPUS] __initdata = { { 0 } };
unsigned prom_cpu_nodes[NR_CPUS];
int linux_num_cpus = 0;
extern void cpu_probe(void); extern void cpu_probe(void);
extern void central_probe(void); extern void central_probe(void);
void __init device_scan(void) static char *cpu_mid_prop(void)
{
if (tlb_type == spitfire)
return "upa-portid";
return "portid";
}
static int check_cpu_node(int nd, int *cur_inst,
int (*compare)(int, int, void *), void *compare_arg,
int *prom_node, int *mid)
{ {
char node_str[128]; char node_str[128];
int nd, prom_node_cpu, thismid;
int cpu_nds[64]; /* One node for each cpu */
int cpu_ctr = 0;
/* FIX ME FAST... -DaveM */ prom_getstring(nd, "device_type", node_str, sizeof(node_str));
ioport_resource.end = 0xffffffffffffffffUL; if (strcmp(node_str, "cpu"))
return -ENODEV;
prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str)); if (!compare(nd, *cur_inst, compare_arg)) {
if (prom_node)
*prom_node = nd;
if (mid)
*mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
return 0;
}
prom_printf("Booting Linux...\n"); (*cur_inst)++;
if(strcmp(node_str, "cpu") == 0) {
cpu_nds[0] = prom_root_node; return -ENODEV;
linux_cpus[0].prom_node = prom_root_node; }
linux_cpus[0].mid = 0;
cpu_ctr++; static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
} else { int *prom_node, int *mid)
int scan; {
scan = prom_getchild(prom_root_node); int nd, cur_inst, err;
/* prom_printf("root child is %08x\n", (unsigned) scan); */
nd = 0; nd = prom_root_node;
while((scan = prom_getsibling(scan)) != 0) { cur_inst = 0;
prom_getstring(scan, "device_type", node_str, sizeof(node_str));
if(strcmp(node_str, "cpu") == 0) { err = check_cpu_node(nd, &cur_inst,
cpu_nds[cpu_ctr] = scan; compare, compare_arg,
linux_cpus[cpu_ctr].prom_node = scan; prom_node, mid);
thismid = 0; if (err == 0)
if (tlb_type == spitfire) { return 0;
prom_getproperty(scan, "upa-portid",
(char *) &thismid, sizeof(thismid)); nd = prom_getchild(nd);
} else if (tlb_type == cheetah || while ((nd = prom_getsibling(nd)) != 0) {
tlb_type == cheetah_plus) { err = check_cpu_node(nd, &cur_inst,
prom_getproperty(scan, "portid", compare, compare_arg,
(char *) &thismid, sizeof(thismid)); prom_node, mid);
} if (err == 0)
linux_cpus[cpu_ctr].mid = thismid; return 0;
printk("Found CPU %d (node=%08x,mid=%d)\n",
cpu_ctr, (unsigned) scan, thismid);
cpu_ctr++;
}
};
if(cpu_ctr == 0) {
prom_printf("No CPU nodes found, cannot continue.\n");
prom_halt();
}
printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
} }
prom_node_cpu = cpu_nds[0];
linux_num_cpus = cpu_ctr; return -ENODEV;
}
prom_cpu_nodes[0] = prom_node_cpu;
static int cpu_instance_compare(int nd, int instance, void *_arg)
{
int desired_instance = (int) (long) _arg;
if (instance == desired_instance)
return 0;
return -ENODEV;
}
int cpu_find_by_instance(int instance, int *prom_node, int *mid)
{
return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
prom_node, mid);
}
static int cpu_mid_compare(int nd, int instance, void *_arg)
{
int desired_mid = (int) (long) _arg;
int this_mid;
this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
if (this_mid == desired_mid)
return 0;
return -ENODEV;
}
int cpu_find_by_mid(int mid, int *prom_node)
{
return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
prom_node, NULL);
}
void __init device_scan(void)
{
/* FIX ME FAST... -DaveM */
ioport_resource.end = 0xffffffffffffffffUL;
prom_printf("Booting Linux...\n");
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
{ {
up_clock_tick = prom_getintdefault(prom_node_cpu, int err, cpu_node;
"clock-frequency", err = cpu_find_by_instance(0, &cpu_node, NULL);
0); if (err) {
prom_printf("No cpu nodes, cannot continue\n");
prom_halt();
}
cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
"clock-frequency",
0);
} }
#endif #endif
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/page.h> #include <asm/page.h>
......
...@@ -628,70 +628,21 @@ spitfire_vpte_base: ...@@ -628,70 +628,21 @@ spitfire_vpte_base:
#undef KERN_HIGHBITS #undef KERN_HIGHBITS
#undef KERN_LOWBITS #undef KERN_LOWBITS
/* Setup Interrupt globals */
wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate
#ifndef CONFIG_SMP
sethi %hi(__up_workvec), %g5
or %g5, %lo(__up_workvec), %g6
#else
/* By definition of where we are, this is boot_cpu. */
brz,pt %i0, not_starfire
sethi %hi(0x1fff4000), %g1
or %g1, %lo(0x1fff4000), %g1
sllx %g1, 12, %g1
or %g1, 0xd0, %g1
lduwa [%g1] ASI_PHYS_BYPASS_EC_E, %g1
b,pt %xcc, set_worklist
nop
not_starfire:
BRANCH_IF_JALAPENO(g1,g5,is_jalapeno)
BRANCH_IF_ANY_CHEETAH(g1,g5,is_cheetah)
ba,pt %xcc, not_cheetah
nop
is_jalapeno:
ldxa [%g0] ASI_JBUS_CONFIG, %g1
srlx %g1, 17, %g1
ba,pt %xcc, set_worklist
and %g1, 0x1f, %g1 ! 5bit JBUS ID
is_cheetah:
ldxa [%g0] ASI_SAFARI_CONFIG, %g1
srlx %g1, 17, %g1
ba,pt %xcc, set_worklist
and %g1, 0x3ff, %g1 ! 10bit Safari Agent ID
not_cheetah:
ldxa [%g0] ASI_UPA_CONFIG, %g1
srlx %g1, 17, %g1
and %g1, 0x1f, %g1
/* In theory this is: &(cpu_data[boot_cpu_id].irq_worklists[0]) */
set_worklist:
sethi %hi(cpu_data), %g5
or %g5, %lo(cpu_data), %g5
sllx %g1, 7, %g1
add %g5, %g1, %g5
add %g5, 64, %g6
#endif
/* Kill PROM timer */ /* Kill PROM timer */
sethi %hi(0x80000000), %g1 sethi %hi(0x80000000), %o2
sllx %g1, 32, %g1 sllx %o2, 32, %o2
wr %g1, 0, %tick_cmpr wr %o2, 0, %tick_cmpr
BRANCH_IF_ANY_CHEETAH(g1,g5,1f) BRANCH_IF_ANY_CHEETAH(o2,o3,1f)
ba,pt %xcc, 2f ba,pt %xcc, 2f
nop nop
/* Disable STICK_INT interrupts. */ /* Disable STICK_INT interrupts. */
1: 1:
sethi %hi(0x80000000), %g1 sethi %hi(0x80000000), %o2
sllx %g1, 32, %g1 sllx %o2, 32, %o2
wr %g1, %asr25 wr %o2, %asr25
/* Ok, we're done setting up all the state our trap mechanims needs, /* Ok, we're done setting up all the state our trap mechanims needs,
* now get back into normal globals and let the PROM know what is up. * now get back into normal globals and let the PROM know what is up.
...@@ -700,6 +651,9 @@ set_worklist: ...@@ -700,6 +651,9 @@ set_worklist:
wrpr %g0, %g0, %wstate wrpr %g0, %g0, %wstate
wrpr %o1, PSTATE_IE, %pstate wrpr %o1, PSTATE_IE, %pstate
call init_irqwork_curcpu
nop
sethi %hi(sparc64_ttable_tl0), %g5 sethi %hi(sparc64_ttable_tl0), %g5
call prom_set_trap_table call prom_set_trap_table
mov %g5, %o0 mov %g5, %o0
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <asm/starfire.h> #include <asm/starfire.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/cpudata.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void distribute_irqs(void); static void distribute_irqs(void);
...@@ -56,12 +57,18 @@ static void distribute_irqs(void); ...@@ -56,12 +57,18 @@ static void distribute_irqs(void);
struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
#ifndef CONFIG_SMP /* This has to be in the main kernel image, it cannot be
unsigned int __up_workvec[16] __attribute__ ((aligned (SMP_CACHE_BYTES))); * turned into per-cpu data. The reason is that the main
#define irq_work(__cpu, __pil) &(__up_workvec[(void)(__cpu), (__pil)]) * kernel image is locked into the TLB and this structure
#else * is accessed from the vectored interrupt trap handler. If
#define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)]) * access to this structure takes a TLB miss it could cause
#endif * the 5-level sparc v9 trap stack to overflow.
*/
struct irq_work_struct {
unsigned int irq_worklists[16];
};
struct irq_work_struct __irq_work[NR_CPUS];
#define irq_work(__cpu, __pil) &(__irq_work[(__cpu)].irq_worklists[(__pil)])
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
/* This is a table of physical addresses used to deal with IBF_DMA_SYNC. /* This is a table of physical addresses used to deal with IBF_DMA_SYNC.
...@@ -706,7 +713,7 @@ static inline void redirect_intr(int cpu, struct ino_bucket *bp) ...@@ -706,7 +713,7 @@ static inline void redirect_intr(int cpu, struct ino_bucket *bp)
goto out; goto out;
/* Voo-doo programming. */ /* Voo-doo programming. */
if (cpu_data[buddy].idle_volume < FORWARD_VOLUME) if (cpu_data(buddy).idle_volume < FORWARD_VOLUME)
goto out; goto out;
/* This just so happens to be correct on Cheetah /* This just so happens to be correct on Cheetah
...@@ -1083,15 +1090,30 @@ void enable_prom_timer(void) ...@@ -1083,15 +1090,30 @@ void enable_prom_timer(void)
prom_timers->count0 = 0; prom_timers->count0 = 0;
} }
void init_irqwork_curcpu(void)
{
register struct irq_work_struct *workp asm("o2");
unsigned long tmp;
memset(__irq_work + smp_processor_id(), 0, sizeof(*workp));
/* Set interrupt globals. */
workp = &__irq_work[smp_processor_id()];
__asm__ __volatile__(
"rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate\n\t"
"mov %2, %%g6\n\t"
"wrpr %0, 0x0, %%pstate\n\t"
: "=&r" (tmp)
: "i" (PSTATE_IG | PSTATE_IE), "r" (workp));
}
/* Only invoked on boot processor. */ /* Only invoked on boot processor. */
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
map_prom_timers(); map_prom_timers();
kill_prom_timer(); kill_prom_timer();
memset(&ivector_table[0], 0, sizeof(ivector_table)); memset(&ivector_table[0], 0, sizeof(ivector_table));
#ifndef CONFIG_SMP
memset(&__up_workvec[0], 0, sizeof(__up_workvec));
#endif
/* We need to clear any IRQ's pending in the soft interrupt /* We need to clear any IRQ's pending in the soft interrupt
* registers, a spurious one could be left around from the * registers, a spurious one could be left around from the
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/oplib.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1518,11 +1519,12 @@ void __init sabre_init(int pnode, char *model_name) ...@@ -1518,11 +1519,12 @@ void __init sabre_init(int pnode, char *model_name)
!strcmp(compat, "pci108e,a001")) { !strcmp(compat, "pci108e,a001")) {
hummingbird_p = 1; hummingbird_p = 1;
} else { } else {
int cpu_node = linux_cpus[0].prom_node; int cpu_node;
/* Of course, Sun has to encode things a thousand /* Of course, Sun has to encode things a thousand
* different ways, inconsistently. * different ways, inconsistently.
*/ */
cpu_find_by_instance(0, &cpu_node, NULL);
if (prom_getproperty(cpu_node, "name", if (prom_getproperty(cpu_node, "name",
compat, sizeof(compat)) > 0 && compat, sizeof(compat)) > 0 &&
!strcmp(compat, "SUNW,UltraSPARC-IIe")) !strcmp(compat, "SUNW,UltraSPARC-IIe"))
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/fpumacro.h> #include <asm/fpumacro.h>
#include <asm/head.h> #include <asm/head.h>
#include <asm/cpudata.h>
/* #define VERBOSE_SHOWREGS */ /* #define VERBOSE_SHOWREGS */
...@@ -84,8 +85,8 @@ int cpu_idle(void) ...@@ -84,8 +85,8 @@ int cpu_idle(void)
/* /*
* the idle loop on a UltraMultiPenguin... * the idle loop on a UltraMultiPenguin...
*/ */
#define idle_me_harder() (cpu_data[smp_processor_id()].idle_volume += 1) #define idle_me_harder() (cpu_data(smp_processor_id()).idle_volume += 1)
#define unidle_me() (cpu_data[smp_processor_id()].idle_volume = 0) #define unidle_me() (cpu_data(smp_processor_id()).idle_volume = 0)
int cpu_idle(void) int cpu_idle(void)
{ {
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
......
...@@ -586,21 +586,15 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) ...@@ -586,21 +586,15 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
/* BUFFER is PAGE_SIZE bytes long. */ /* BUFFER is PAGE_SIZE bytes long. */
extern char *sparc_cpu_type[]; extern char *sparc_cpu_type;
extern char *sparc_fpu_type[]; extern char *sparc_fpu_type;
extern void smp_info(struct seq_file *); extern void smp_info(struct seq_file *);
extern void smp_bogo(struct seq_file *); extern void smp_bogo(struct seq_file *);
extern void mmu_info(struct seq_file *); extern void mmu_info(struct seq_file *);
#ifndef CONFIG_SMP
unsigned long up_clock_tick;
#endif
static int show_cpuinfo(struct seq_file *m, void *__unused) static int show_cpuinfo(struct seq_file *m, void *__unused)
{ {
int cpuid = smp_processor_id();
seq_printf(m, seq_printf(m,
"cpu\t\t: %s\n" "cpu\t\t: %s\n"
"fpu\t\t: %s\n" "fpu\t\t: %s\n"
...@@ -614,18 +608,18 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) ...@@ -614,18 +608,18 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
"Cpu0ClkTck\t: %016lx\n" "Cpu0ClkTck\t: %016lx\n"
#endif #endif
, ,
sparc_cpu_type[cpuid], sparc_cpu_type,
sparc_fpu_type[cpuid], sparc_fpu_type,
prom_rev, prom_rev,
prom_prev >> 16, prom_prev >> 16,
(prom_prev >> 8) & 0xff, (prom_prev >> 8) & 0xff,
prom_prev & 0xff, prom_prev & 0xff,
(long)linux_num_cpus, (long)num_possible_cpus(),
(long)num_online_cpus() (long)num_online_cpus()
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
, loops_per_jiffy/(500000/HZ), , cpu_data(0).udelay_val/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100, (cpu_data(0).udelay_val/(5000/HZ)) % 100,
up_clock_tick cpu_data(0).clock_tick
#endif #endif
); );
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -680,21 +674,24 @@ void sun_do_break(void) ...@@ -680,21 +674,24 @@ void sun_do_break(void)
int serial_console; int serial_console;
int stop_a_enabled = 1; int stop_a_enabled = 1;
static struct cpu *sparc64_cpus;
static int __init topology_init(void) static int __init topology_init(void)
{ {
int i; int i, err;
sparc64_cpus = kmalloc(NR_CPUS * sizeof(struct cpu), GFP_KERNEL); err = -ENOMEM;
if (!sparc64_cpus)
return -ENOMEM;
memset(sparc64_cpus, 0, NR_CPUS * sizeof(struct cpu));
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i)) if (cpu_possible(i)) {
register_cpu(&sparc64_cpus[i], i, NULL); struct cpu *p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p) {
memset(p, 0, sizeof(*p));
register_cpu(p, i, NULL);
err = 0;
}
}
} }
return 0;
return err;
} }
subsys_initcall(topology_init); subsys_initcall(topology_init);
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/cpudata.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -41,8 +42,6 @@ ...@@ -41,8 +42,6 @@
extern int linux_num_cpus; extern int linux_num_cpus;
extern void calibrate_delay(void); extern void calibrate_delay(void);
cpuinfo_sparc cpu_data[NR_CPUS];
/* Please don't make this stuff initdata!!! --DaveM */ /* Please don't make this stuff initdata!!! --DaveM */
static unsigned char boot_cpu_id; static unsigned char boot_cpu_id;
...@@ -73,35 +72,29 @@ void smp_bogo(struct seq_file *m) ...@@ -73,35 +72,29 @@ void smp_bogo(struct seq_file *m)
seq_printf(m, seq_printf(m,
"Cpu%dBogo\t: %lu.%02lu\n" "Cpu%dBogo\t: %lu.%02lu\n"
"Cpu%dClkTck\t: %016lx\n", "Cpu%dClkTck\t: %016lx\n",
i, cpu_data[i].udelay_val / (500000/HZ), i, cpu_data(i).udelay_val / (500000/HZ),
(cpu_data[i].udelay_val / (5000/HZ)) % 100, (cpu_data(i).udelay_val / (5000/HZ)) % 100,
i, cpu_data[i].clock_tick); i, cpu_data(i).clock_tick);
} }
void __init smp_store_cpu_info(int id) void __init smp_store_cpu_info(int id)
{ {
int i, no; int cpu_node;
/* multiplier and counter set by /* multiplier and counter set by
smp_setup_percpu_timer() */ smp_setup_percpu_timer() */
cpu_data[id].udelay_val = loops_per_jiffy; cpu_data(id).udelay_val = loops_per_jiffy;
for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == id)
break;
cpu_data[id].clock_tick = prom_getintdefault(linux_cpus[no].prom_node, cpu_find_by_mid(id, &cpu_node);
cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
"clock-frequency", 0); "clock-frequency", 0);
cpu_data[id].pgcache_size = 0; cpu_data(id).pgcache_size = 0;
cpu_data[id].pte_cache[0] = NULL; cpu_data(id).pte_cache[0] = NULL;
cpu_data[id].pte_cache[1] = NULL; cpu_data(id).pte_cache[1] = NULL;
cpu_data[id].pgdcache_size = 0; cpu_data(id).pgdcache_size = 0;
cpu_data[id].pgd_cache = NULL; cpu_data(id).pgd_cache = NULL;
cpu_data[id].idle_volume = 1; cpu_data(id).idle_volume = 1;
for (i = 0; i < 16; i++)
cpu_data[id].irq_worklists[i] = 0;
} }
static void smp_setup_percpu_timer(void); static void smp_setup_percpu_timer(void);
...@@ -109,7 +102,6 @@ static void smp_setup_percpu_timer(void); ...@@ -109,7 +102,6 @@ static void smp_setup_percpu_timer(void);
static volatile unsigned long callin_flag = 0; static volatile unsigned long callin_flag = 0;
extern void inherit_locked_prom_mappings(int save_p); extern void inherit_locked_prom_mappings(int save_p);
extern void cpu_probe(void);
void __init smp_callin(void) void __init smp_callin(void)
{ {
...@@ -129,8 +121,6 @@ void __init smp_callin(void) ...@@ -129,8 +121,6 @@ void __init smp_callin(void)
__flush_cache_all(); __flush_cache_all();
__flush_tlb_all(); __flush_tlb_all();
cpu_probe();
smp_setup_percpu_timer(); smp_setup_percpu_timer();
local_irq_enable(); local_irq_enable();
...@@ -300,8 +290,6 @@ static void smp_synchronize_one_tick(int cpu) ...@@ -300,8 +290,6 @@ static void smp_synchronize_one_tick(int cpu)
spin_unlock_irqrestore(&itc_sync_lock, flags); spin_unlock_irqrestore(&itc_sync_lock, flags);
} }
extern struct prom_cpuinfo linux_cpus[NR_CPUS];
extern unsigned long sparc64_cpu_startup; extern unsigned long sparc64_cpu_startup;
/* The OBP cpu startup callback truncates the 3rd arg cookie to /* The OBP cpu startup callback truncates the 3rd arg cookie to
...@@ -317,7 +305,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) ...@@ -317,7 +305,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
unsigned long cookie = unsigned long cookie =
(unsigned long)(&cpu_new_thread); (unsigned long)(&cpu_new_thread);
struct task_struct *p; struct task_struct *p;
int timeout, no, ret; int timeout, ret, cpu_node;
kernel_thread(NULL, NULL, CLONE_IDLETASK); kernel_thread(NULL, NULL, CLONE_IDLETASK);
...@@ -328,19 +316,18 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) ...@@ -328,19 +316,18 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
unhash_process(p); unhash_process(p);
callin_flag = 0; callin_flag = 0;
for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == cpu)
break;
cpu_new_thread = p->thread_info; cpu_new_thread = p->thread_info;
cpu_set(cpu, cpu_callout_map); cpu_set(cpu, cpu_callout_map);
prom_startcpu(linux_cpus[no].prom_node, entry, cookie);
cpu_find_by_mid(cpu, &cpu_node);
prom_startcpu(cpu_node, entry, cookie);
for (timeout = 0; timeout < 5000000; timeout++) { for (timeout = 0; timeout < 5000000; timeout++) {
if (callin_flag) if (callin_flag)
break; break;
udelay(100); udelay(100);
} }
if (callin_flag) { if (callin_flag) {
prom_cpu_nodes[cpu] = linux_cpus[no].prom_node;
ret = 0; ret = 0;
} else { } else {
printk("Processor %d is stuck.\n", cpu); printk("Processor %d is stuck.\n", cpu);
...@@ -1048,8 +1035,8 @@ void smp_promstop_others(void) ...@@ -1048,8 +1035,8 @@ void smp_promstop_others(void)
extern void sparc64_do_profile(struct pt_regs *regs); extern void sparc64_do_profile(struct pt_regs *regs);
#define prof_multiplier(__cpu) cpu_data[(__cpu)].multiplier #define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
#define prof_counter(__cpu) cpu_data[(__cpu)].counter #define prof_counter(__cpu) cpu_data(__cpu).counter
void smp_percpu_timer_interrupt(struct pt_regs *regs) void smp_percpu_timer_interrupt(struct pt_regs *regs)
{ {
...@@ -1141,7 +1128,6 @@ void __init smp_tick_init(void) ...@@ -1141,7 +1128,6 @@ void __init smp_tick_init(void)
} }
cpu_set(boot_cpu_id, cpu_online_map); cpu_set(boot_cpu_id, cpu_online_map);
prom_cpu_nodes[boot_cpu_id] = linux_cpus[0].prom_node;
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1; prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
} }
...@@ -1155,6 +1141,7 @@ static void __init smp_tune_scheduling(void) ...@@ -1155,6 +1141,7 @@ static void __init smp_tune_scheduling(void)
unsigned long orig_flush_base, flush_base, flags, *p; unsigned long orig_flush_base, flush_base, flags, *p;
unsigned int ecache_size, order; unsigned int ecache_size, order;
cycles_t tick1, tick2, raw; cycles_t tick1, tick2, raw;
int cpu_node;
/* Approximate heuristic for SMP scheduling. It is an /* Approximate heuristic for SMP scheduling. It is an
* estimation of the time it takes to flush the L2 cache * estimation of the time it takes to flush the L2 cache
...@@ -1172,7 +1159,8 @@ static void __init smp_tune_scheduling(void) ...@@ -1172,7 +1159,8 @@ static void __init smp_tune_scheduling(void)
goto report; goto report;
} }
ecache_size = prom_getintdefault(linux_cpus[0].prom_node, cpu_find_by_instance(0, &cpu_node, NULL);
ecache_size = prom_getintdefault(cpu_node,
"ecache-size", (512 * 1024)); "ecache-size", (512 * 1024));
if (ecache_size > (4 * 1024 * 1024)) if (ecache_size > (4 * 1024 * 1024))
ecache_size = (4 * 1024 * 1024); ecache_size = (4 * 1024 * 1024);
...@@ -1254,22 +1242,27 @@ int setup_profiling_timer(unsigned int multiplier) ...@@ -1254,22 +1242,27 @@ int setup_profiling_timer(unsigned int multiplier)
void __init smp_prepare_cpus(unsigned int max_cpus) void __init smp_prepare_cpus(unsigned int max_cpus)
{ {
int i; int instance, mid;
for (i = 0; i < linux_num_cpus; i++) { instance = 0;
if (linux_cpus[i].mid < max_cpus) { while (!cpu_find_by_instance(instance, NULL, &mid)) {
cpu_set(linux_cpus[i].mid, phys_cpu_present_map); if (mid < max_cpus) {
cpu_set(mid, phys_cpu_present_map);
atomic_inc(&sparc64_num_cpus_possible); atomic_inc(&sparc64_num_cpus_possible);
} }
instance++;
} }
if (atomic_read(&sparc64_num_cpus_possible) > max_cpus) { if (atomic_read(&sparc64_num_cpus_possible) > max_cpus) {
for (i = linux_num_cpus - 1; i >= 0; i--) { instance = 0;
if (linux_cpus[i].mid != boot_cpu_id) { while (!cpu_find_by_instance(instance, NULL, &mid)) {
cpu_clear(linux_cpus[i].mid, phys_cpu_present_map); if (mid != boot_cpu_id) {
cpu_clear(mid, phys_cpu_present_map);
atomic_dec(&sparc64_num_cpus_possible); atomic_dec(&sparc64_num_cpus_possible);
if (atomic_read(&sparc64_num_cpus_possible) <= max_cpus) if (atomic_read(&sparc64_num_cpus_possible) <= max_cpus)
break; break;
} }
instance++;
} }
} }
...@@ -1306,7 +1299,7 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -1306,7 +1299,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i)) if (cpu_online(i))
bogosum += cpu_data[i].udelay_val; bogosum += cpu_data(i).udelay_val;
} }
printk("Total of %ld processors activated " printk("Total of %ld processors activated "
"(%lu.%02lu BogoMIPS).\n", "(%lu.%02lu BogoMIPS).\n",
...@@ -1319,3 +1312,27 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -1319,3 +1312,27 @@ void __init smp_cpus_done(unsigned int max_cpus)
*/ */
smp_tune_scheduling(); smp_tune_scheduling();
} }
/* This needn't do anything as we do not sleep the cpu
* inside of the idler task, so an interrupt is not needed
* to get a clean fast response.
*
* XXX Reverify this assumption... -DaveM
*
* Addendum: We do want it to do something for the signal
* delivery case, we detect that by just seeing
* if we are trying to send this to an idler or not.
*/
void smp_send_reschedule(int cpu)
{
if (cpu_data(cpu).idle_volume == 0)
smp_receive_signal(cpu);
}
/* This is a nop because we capture all other cpus
* anyways when making the PROM active.
*/
void smp_send_stop(void)
{
}
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/fs_struct.h> #include <linux/fs_struct.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/percpu.h>
#include <net/compat.h> #include <net/compat.h>
#include <asm/oplib.h> #include <asm/oplib.h>
...@@ -55,6 +56,7 @@ ...@@ -55,6 +56,7 @@
#include <asm/a.out.h> #include <asm/a.out.h>
#include <asm/ns87303.h> #include <asm/ns87303.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/cpudata.h>
struct poll { struct poll {
int fd; int fd;
...@@ -124,6 +126,9 @@ extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *, ...@@ -124,6 +126,9 @@ extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *, extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
unsigned long *, unsigned long *, unsigned long *); unsigned long *, unsigned long *, unsigned long *);
/* Per-CPU information table */
EXPORT_PER_CPU_SYMBOL(__cpu_data);
/* used by various drivers */ /* used by various drivers */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#ifndef CONFIG_DEBUG_SPINLOCK #ifndef CONFIG_DEBUG_SPINLOCK
...@@ -142,9 +147,6 @@ extern void mcount(void); ...@@ -142,9 +147,6 @@ extern void mcount(void);
EXPORT_SYMBOL_NOVERS(mcount); EXPORT_SYMBOL_NOVERS(mcount);
#endif #endif
/* Per-CPU information table */
EXPORT_SYMBOL(cpu_data);
/* CPU online map and active count. */ /* CPU online map and active count. */
EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(phys_cpu_present_map);
...@@ -320,7 +322,6 @@ EXPORT_SYMBOL(sys_getegid); ...@@ -320,7 +322,6 @@ EXPORT_SYMBOL(sys_getegid);
EXPORT_SYMBOL(sys_getgid); EXPORT_SYMBOL(sys_getgid);
EXPORT_SYMBOL(svr4_getcontext); EXPORT_SYMBOL(svr4_getcontext);
EXPORT_SYMBOL(svr4_setcontext); EXPORT_SYMBOL(svr4_setcontext);
EXPORT_SYMBOL(prom_cpu_nodes);
EXPORT_SYMBOL(sys_ioctl); EXPORT_SYMBOL(sys_ioctl);
EXPORT_SYMBOL(compat_sys_ioctl); EXPORT_SYMBOL(compat_sys_ioctl);
EXPORT_SYMBOL(sparc32_open); EXPORT_SYMBOL(sparc32_open);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asm/starfire.h> #include <asm/starfire.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/cpudata.h>
spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED; spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
...@@ -956,7 +957,7 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc ...@@ -956,7 +957,7 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc
clock = prom_getint(node, "stick-frequency"); clock = prom_getint(node, "stick-frequency");
} else { } else {
tick_ops = &tick_operations; tick_ops = &tick_operations;
node = linux_cpus[0].prom_node; cpu_find_by_instance(0, &node, NULL);
clock = prom_getint(node, "clock-frequency"); clock = prom_getint(node, "clock-frequency");
} }
} else { } else {
...@@ -1012,11 +1013,7 @@ unsigned long sparc64_get_clock_tick(unsigned int cpu) ...@@ -1012,11 +1013,7 @@ unsigned long sparc64_get_clock_tick(unsigned int cpu)
if (ft->clock_tick_ref) if (ft->clock_tick_ref)
return ft->clock_tick_ref; return ft->clock_tick_ref;
#ifdef CONFIG_SMP return cpu_data(cpu).clock_tick;
return cpu_data[cpu].clock_tick;
#else
return up_clock_tick;
#endif
} }
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
...@@ -1028,35 +1025,22 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val ...@@ -1028,35 +1025,22 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
unsigned int cpu = freq->cpu; unsigned int cpu = freq->cpu;
struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu);
#ifdef CONFIG_SMP
if (!ft->ref_freq) { if (!ft->ref_freq) {
ft->ref_freq = freq->old; ft->ref_freq = freq->old;
ft->udelay_val_ref = cpu_data[cpu].udelay_val; ft->udelay_val_ref = cpu_data(cpu).udelay_val;
ft->clock_tick_ref = cpu_data[cpu].clock_tick; ft->clock_tick_ref = cpu_data(cpu).clock_tick;
} }
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
cpu_data[cpu].udelay_val = cpu_data(cpu).udelay_val =
cpufreq_scale(ft->udelay_val_ref, cpufreq_scale(ft->udelay_val_ref,
ft->ref_freq, ft->ref_freq,
freq->new); freq->new);
cpu_data[cpu].clock_tick = cpu_data(cpu).clock_tick =
cpufreq_scale(ft->clock_tick_ref, cpufreq_scale(ft->clock_tick_ref,
ft->ref_freq, ft->ref_freq,
freq->new); freq->new);
} }
#else
/* In the non-SMP case, kernel/cpufreq.c takes care of adjusting
* loops_per_jiffy.
*/
if (!ft->ref_freq) {
ft->ref_freq = freq->old;
ft->clock_tick_ref = up_clock_tick;
}
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new))
up_clock_tick = cpufreq_scale(ft->clock_tick_ref, ft->ref_freq, freq->new);
#endif
return 0; return 0;
} }
......
...@@ -246,20 +246,12 @@ startup_continue: ...@@ -246,20 +246,12 @@ startup_continue:
wrpr %o1, 0x0, %pstate wrpr %o1, 0x0, %pstate
ldx [%g6 + TI_TASK], %g4 ldx [%g6 + TI_TASK], %g4
/* Setup interrupt globals, we are always SMP. */ wrpr %g0, 0, %wstate
wrpr %o1, PSTATE_IG, %pstate
/* Get our UPA MID. */
ldub [%o2 + TI_CPU], %g1
sethi %hi(cpu_data), %g5
or %g5, %lo(cpu_data), %g5
/* In theory this is: &(cpu_data[this_upamid].irq_worklists[0]) */ call init_irqwork_curcpu
sllx %g1, 7, %g1 nop
add %g5, %g1, %g1
add %g1, 64, %g6
wrpr %g0, 0, %wstate rdpr %pstate, %o1
or %o1, PSTATE_IE, %o1 or %o1, PSTATE_IE, %o1
wrpr %o1, 0, %pstate wrpr %o1, 0, %pstate
......
...@@ -613,8 +613,7 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector ...@@ -613,8 +613,7 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector
void __init cheetah_ecache_flush_init(void) void __init cheetah_ecache_flush_init(void)
{ {
unsigned long largest_size, smallest_linesize, order, ver; unsigned long largest_size, smallest_linesize, order, ver;
char type[16]; int node, i, instance;
int node, i;
/* Scan all cpu device tree nodes, note two values: /* Scan all cpu device tree nodes, note two values:
* 1) largest E-cache size * 1) largest E-cache size
...@@ -622,21 +621,21 @@ void __init cheetah_ecache_flush_init(void) ...@@ -622,21 +621,21 @@ void __init cheetah_ecache_flush_init(void)
*/ */
largest_size = 0UL; largest_size = 0UL;
smallest_linesize = ~0UL; smallest_linesize = ~0UL;
node = prom_getchild(prom_root_node);
while ((node = prom_getsibling(node)) != 0) { instance = 0;
prom_getstring(node, "device_type", type, sizeof(type)); while (!cpu_find_by_instance(instance, &node, NULL)) {
if (!strcmp(type, "cpu")) { unsigned long val;
unsigned long val;
val = prom_getintdefault(node, "ecache-size",
val = prom_getintdefault(node, "ecache-size", (2 * 1024 * 1024));
(2 * 1024 * 1024)); if (val > largest_size)
if (val > largest_size) largest_size = val;
largest_size = val; val = prom_getintdefault(node, "ecache-line-size", 64);
val = prom_getintdefault(node, "ecache-line-size", 64); if (val < smallest_linesize)
if (val < smallest_linesize) smallest_linesize = val;
smallest_linesize = val; instance++;
}
} }
if (largest_size == 0UL || smallest_linesize == ~0UL) { if (largest_size == 0UL || smallest_linesize == ~0UL) {
prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache " prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache "
"parameters.\n"); "parameters.\n");
......
...@@ -1706,6 +1706,10 @@ void __init mem_init(void) ...@@ -1706,6 +1706,10 @@ void __init mem_init(void)
unsigned long addr, last; unsigned long addr, last;
int i; int i;
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
#endif
i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
i += 1; i += 1;
sparc64_valid_addr_bitmap = (unsigned long *) sparc64_valid_addr_bitmap = (unsigned long *)
......
...@@ -349,8 +349,7 @@ asmlinkage int solaris_sysconf(int id) ...@@ -349,8 +349,7 @@ asmlinkage int solaris_sysconf(int id)
case SOLARIS_CONFIG_XOPEN_VER: return 3; case SOLARIS_CONFIG_XOPEN_VER: return 3;
case SOLARIS_CONFIG_CLK_TCK: case SOLARIS_CONFIG_CLK_TCK:
case SOLARIS_CONFIG_PROF_TCK: case SOLARIS_CONFIG_PROF_TCK:
return prom_getintdefault(prom_cpu_nodes[smp_processor_id()], return sparc64_get_clock_tick(smp_processor_id());
"clock-frequency", 167000000);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS; case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS;
case SOLARIS_CONFIG_NPROC_ONLN: return num_online_cpus(); case SOLARIS_CONFIG_NPROC_ONLN: return num_online_cpus();
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/console.h> #include <linux/console.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
#define cpus_coerce(map) (map) #define cpus_coerce(map) (map)
#define cpu_set(cpu, map) do { cpus_coerce(map) = 1UL; } while (0) #define cpu_set(cpu, map) do { (void)(cpu); cpus_coerce(map) = 1UL; } while (0)
#define cpu_clear(cpu, map) do { cpus_coerce(map) = 0UL; } while (0) #define cpu_clear(cpu, map) do { (void)(cpu); cpus_coerce(map) = 0UL; } while (0)
#define cpu_isset(cpu, map) (cpus_coerce(map) != 0UL) #define cpu_isset(cpu, map) ((void)(cpu), cpus_coerce(map) != 0UL)
#define cpu_test_and_set(cpu, map) test_and_set_bit(0, (map).mask) #define cpu_test_and_set(cpu, map) ((void)(cpu), test_and_set_bit(0, (map).mask))
#define cpus_and(dst, src1, src2) \ #define cpus_and(dst, src1, src2) \
do { \ do { \
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
cpus_coerce(__tmp__) = map; \ cpus_coerce(__tmp__) = map; \
__tmp__; \ __tmp__; \
}) })
#define cpumask_of_cpu(cpu) cpus_promote(1) #define cpumask_of_cpu(cpu) ((void)(cpu), cpus_promote(1))
#define any_online_cpu(map) (cpus_coerce(map) ? 0 : 1) #define any_online_cpu(map) (cpus_coerce(map) ? 0 : 1)
/* /*
......
/* cpudata.h: Per-cpu parameters.
*
* Copyright (C) 2003 David S. Miller (davem@redhat.com)
*/
#ifndef _SPARC64_CPUDATA_H
#define _SPARC64_CPUDATA_H
#include <linux/percpu.h>
typedef struct {
/* Dcache line 1 */
unsigned int __pad0; /* bh_count moved to irq_stat for consistency. KAO */
unsigned int multiplier;
unsigned int counter;
unsigned int idle_volume;
unsigned long clock_tick; /* %tick's per second */
unsigned long udelay_val;
/* Dcache line 2 */
unsigned int pgcache_size;
unsigned int pgdcache_size;
unsigned long *pte_cache[2];
unsigned long *pgd_cache;
} cpuinfo_sparc;
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
#endif /* _SPARC64_CPUDATA_H */
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/param.h> #include <linux/param.h>
#include <asm/cpudata.h>
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -58,11 +59,7 @@ extern __inline__ void __ndelay(unsigned long usecs, unsigned long lps) ...@@ -58,11 +59,7 @@ extern __inline__ void __ndelay(unsigned long usecs, unsigned long lps)
__delay(usecs * HZ); __delay(usecs * HZ);
} }
#ifdef CONFIG_SMP #define __udelay_val cpu_data(smp_processor_id()).udelay_val
#define __udelay_val cpu_data[smp_processor_id()].udelay_val
#else
#define __udelay_val loops_per_jiffy
#endif
#define udelay(usecs) __udelay((usecs),__udelay_val) #define udelay(usecs) __udelay((usecs),__udelay_val)
#define ndelay(usecs) __ndelay((usecs),__udelay_val) #define ndelay(usecs) __ndelay((usecs),__udelay_val)
......
...@@ -121,13 +121,6 @@ extern void disable_irq(unsigned int); ...@@ -121,13 +121,6 @@ extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int); extern void enable_irq(unsigned int);
extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap); extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap);
extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
extern unsigned int psycho_build_irq(void *psycho, int imap_off, int ino, int need_dma_sync);
#ifdef CONFIG_SMP
extern void set_cpu_int(int, int);
extern void clear_cpu_int(int, int);
extern void set_irq_udt(int);
#endif
extern int request_fast_irq(unsigned int irq, extern int request_fast_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *), irqreturn_t (*handler)(int, void *, struct pt_regs *),
......
...@@ -327,6 +327,10 @@ extern int prom_setprop(int node, char *prop_name, char *prop_value, ...@@ -327,6 +327,10 @@ extern int prom_setprop(int node, char *prop_name, char *prop_value,
extern int prom_pathtoinode(char *path); extern int prom_pathtoinode(char *path);
extern int prom_inst2pkg(int); extern int prom_inst2pkg(int);
/* CPU probing helpers. */
int cpu_find_by_instance(int instance, int *prom_node, int *mid);
int cpu_find_by_mid(int mid, int *prom_node);
/* Client interface level routines. */ /* Client interface level routines. */
extern void prom_set_trap_table(unsigned long tba); extern void prom_set_trap_table(unsigned long tba);
......
...@@ -10,11 +10,12 @@ ...@@ -10,11 +10,12 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/cpudata.h>
/* Page table allocation/freeing. */ /* Page table allocation/freeing. */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Sliiiicck */ /* Sliiiicck */
#define pgt_quicklists cpu_data[smp_processor_id()] #define pgt_quicklists cpu_data(smp_processor_id())
#else #else
extern struct pgtable_cache_struct { extern struct pgtable_cache_struct {
unsigned long *pgd_cache; unsigned long *pgd_cache;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/delay.h>
/* Bus types */ /* Bus types */
#define EISA_bus 0 #define EISA_bus 0
......
...@@ -17,49 +17,12 @@ ...@@ -17,49 +17,12 @@
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/cache.h> #include <linux/cache.h>
/* PROM provided per-processor information we need
* to start them all up.
*/
struct prom_cpuinfo {
int prom_node;
int mid;
};
extern int linux_num_cpus; /* number of CPUs probed */
extern struct prom_cpuinfo linux_cpus[NR_CPUS];
extern unsigned int prom_cpu_nodes[NR_CPUS];
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/* Per processor Sparc parameters we need. */
/* Keep this a multiple of 64-bytes for cache reasons. */
typedef struct {
/* Dcache line 1 */
unsigned int __pad0; /* bh_count moved to irq_stat for consistency. KAO */
unsigned int multiplier;
unsigned int counter;
unsigned int idle_volume;
unsigned long clock_tick; /* %tick's per second */
unsigned long udelay_val;
/* Dcache line 2 */
unsigned int pgcache_size;
unsigned int pgdcache_size;
unsigned long *pte_cache[2];
unsigned long *pgd_cache;
/* Dcache lines 3 and 4 */
unsigned int irq_worklists[16];
} ____cacheline_aligned cpuinfo_sparc;
extern cpuinfo_sparc cpu_data[NR_CPUS];
/* /*
* Private routines/data * Private routines/data
*/ */
...@@ -110,29 +73,11 @@ static __inline__ int hard_smp_processor_id(void) ...@@ -110,29 +73,11 @@ static __inline__ int hard_smp_processor_id(void)
#define smp_processor_id() (current_thread_info()->cpu) #define smp_processor_id() (current_thread_info()->cpu)
/* This needn't do anything as we do not sleep the cpu #endif /* !(__ASSEMBLY__) */
* inside of the idler task, so an interrupt is not needed
* to get a clean fast response.
*
* XXX Reverify this assumption... -DaveM
*
* Addendum: We do want it to do something for the signal
* delivery case, we detect that by just seeing
* if we are trying to send this to an idler or not.
*/
static __inline__ void smp_send_reschedule(int cpu)
{
extern void smp_receive_signal(int);
if (cpu_data[cpu].idle_volume == 0)
smp_receive_signal(cpu);
}
/* This is a nop as well because we capture all other cpus #else
* anyways when making the PROM active.
*/
static __inline__ void smp_send_stop(void) { }
#endif /* !(__ASSEMBLY__) */ #define num_possible_cpus() (1)
#endif /* !(CONFIG_SMP) */ #endif /* !(CONFIG_SMP) */
......
...@@ -69,10 +69,6 @@ struct pt_regs; ...@@ -69,10 +69,6 @@ struct pt_regs;
extern void timer_tick_interrupt(struct pt_regs *); extern void timer_tick_interrupt(struct pt_regs *);
#endif #endif
#ifndef CONFIG_SMP
extern unsigned long up_clock_tick;
#endif
extern unsigned long sparc64_get_clock_tick(unsigned int cpu); extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
#endif /* _SPARC64_TIMER_H */ #endif /* _SPARC64_TIMER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment