Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
Browse files Browse the repository at this point in the history
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC]: Try to start getting SMP back into shape.
  • Loading branch information
Linus Torvalds committed Mar 25, 2006
2 parents b55813a + a54123e commit d71eecf
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 178 deletions.
1 change: 0 additions & 1 deletion arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ menu "General machine setup"

config SMP
bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
depends on BROKEN
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
Expand Down
66 changes: 34 additions & 32 deletions arch/sparc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,11 @@ void (*sparc_init_timers)(irqreturn_t (*)(int, void *,struct pt_regs *)) =
struct irqaction static_irqaction[MAX_STATIC_ALLOC];
int static_irq_count;

struct irqaction *irq_action[NR_IRQS] = {
[0 ... (NR_IRQS-1)] = NULL
};
struct {
struct irqaction *action;
int flags;
} sparc_irq[NR_IRQS];
#define SPARC_IRQ_INPROGRESS 1

/* Used to protect the IRQ action lists */
DEFINE_SPINLOCK(irq_action_lock);
Expand All @@ -177,7 +179,7 @@ int show_interrupts(struct seq_file *p, void *v)
}
spin_lock_irqsave(&irq_action_lock, flags);
if (i < NR_IRQS) {
action = *(i + irq_action);
action = sparc_irq[i].action;
if (!action)
goto out_unlock;
seq_printf(p, "%3d: ", i);
Expand All @@ -186,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else
for_each_online_cpu(j) {
seq_printf(p, "%10u ",
kstat_cpu(cpu_logical_map(j)).irqs[i]);
kstat_cpu(j).irqs[i]);
}
#endif
seq_printf(p, " %c %s",
Expand All @@ -207,7 +209,7 @@ int show_interrupts(struct seq_file *p, void *v)
void free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action;
struct irqaction * tmp = NULL;
struct irqaction **actionp;
unsigned long flags;
unsigned int cpu_irq;

Expand All @@ -225,7 +227,8 @@ void free_irq(unsigned int irq, void *dev_id)

spin_lock_irqsave(&irq_action_lock, flags);

action = *(cpu_irq + irq_action);
actionp = &sparc_irq[cpu_irq].action;
action = *actionp;

if (!action->handler) {
printk("Trying to free free IRQ%d\n",irq);
Expand All @@ -235,7 +238,7 @@ void free_irq(unsigned int irq, void *dev_id)
for (; action; action = action->next) {
if (action->dev_id == dev_id)
break;
tmp = action;
actionp = &action->next;
}
if (!action) {
printk("Trying to free free shared IRQ%d\n",irq);
Expand All @@ -254,11 +257,8 @@ void free_irq(unsigned int irq, void *dev_id)
irq, action->name);
goto out_unlock;
}

if (action && tmp)
tmp->next = action->next;
else
*(cpu_irq + irq_action) = action->next;

*actionp = action->next;

spin_unlock_irqrestore(&irq_action_lock, flags);

Expand All @@ -268,7 +268,7 @@ void free_irq(unsigned int irq, void *dev_id)

kfree(action);

if (!(*(cpu_irq + irq_action)))
if (!sparc_irq[cpu_irq].action)
disable_irq(irq);

out_unlock:
Expand All @@ -287,8 +287,11 @@ EXPORT_SYMBOL(free_irq);
#ifdef CONFIG_SMP
void synchronize_irq(unsigned int irq)
{
printk("synchronize_irq says: implement me!\n");
BUG();
unsigned int cpu_irq;

cpu_irq = irq & (NR_IRQS - 1);
while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
cpu_relax();
}
#endif /* SMP */

Expand All @@ -299,7 +302,7 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
unsigned int cpu_irq;

cpu_irq = irq & (NR_IRQS - 1);
action = *(cpu_irq + irq_action);
action = sparc_irq[cpu_irq].action;

printk("IO device interrupt, irq = %d\n", irq);
printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
Expand Down Expand Up @@ -330,14 +333,16 @@ void handler_irq(int irq, struct pt_regs * regs)
if(irq < 10)
smp4m_irq_rotate(cpu);
#endif
action = *(irq + irq_action);
action = sparc_irq[irq].action;
sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
kstat_cpu(cpu).irqs[irq]++;
do {
if (!action || !action->handler)
unexpected_irq(irq, NULL, regs);
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
enable_pil_irq(irq);
irq_exit();
}
Expand Down Expand Up @@ -389,7 +394,7 @@ int request_fast_irq(unsigned int irq,

spin_lock_irqsave(&irq_action_lock, flags);

action = *(cpu_irq + irq_action);
action = sparc_irq[cpu_irq].action;
if(action) {
if(action->flags & SA_SHIRQ)
panic("Trying to register fast irq when already shared.\n");
Expand Down Expand Up @@ -452,7 +457,7 @@ int request_fast_irq(unsigned int irq,
action->dev_id = NULL;
action->next = NULL;

*(cpu_irq + irq_action) = action;
sparc_irq[cpu_irq].action = action;

enable_irq(irq);

Expand All @@ -467,7 +472,7 @@ int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
{
struct irqaction * action, *tmp = NULL;
struct irqaction * action, **actionp;
unsigned long flags;
unsigned int cpu_irq;
int ret;
Expand All @@ -490,20 +495,20 @@ int request_irq(unsigned int irq,

spin_lock_irqsave(&irq_action_lock, flags);

action = *(cpu_irq + irq_action);
actionp = &sparc_irq[cpu_irq].action;
action = *actionp;
if (action) {
if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
for (tmp = action; tmp->next; tmp = tmp->next);
} else {
if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) {
ret = -EBUSY;
goto out_unlock;
}
if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
if ((action->flags & SA_INTERRUPT) != (irqflags & SA_INTERRUPT)) {
printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
ret = -EBUSY;
goto out_unlock;
}
action = NULL; /* Or else! */
}
for ( ; action; action = *actionp)
actionp = &action->next;
}

/* If this is flagged as statically allocated then we use our
Expand Down Expand Up @@ -532,10 +537,7 @@ int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;

if (tmp)
tmp->next = action;
else
*(cpu_irq + irq_action) = action;
*actionp = action;

enable_irq(irq);

Expand Down
84 changes: 63 additions & 21 deletions arch/sparc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS];

cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
cpumask_t smp_commenced_mask = CPU_MASK_NONE;

/* The only guaranteed locking primitive available on all Sparc
* processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
Expand All @@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
/* Used to make bitops atomic */
unsigned char bitops_spinlock = 0;

volatile unsigned long ipi_count;

volatile int smp_process_available=0;
volatile int smp_commenced = 0;

void __init smp_store_cpu_info(int id)
{
int cpu_node;
Expand All @@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id)

void __init smp_cpus_done(unsigned int max_cpus)
{
extern void smp4m_smp_done(void);
unsigned long bogosum = 0;
int cpu, num;

for (cpu = 0, num = 0; cpu < NR_CPUS; cpu++)
if (cpu_online(cpu)) {
num++;
bogosum += cpu_data(cpu).udelay_val;
}

printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
num, bogosum/(500000/HZ),
(bogosum/(5000/HZ))%100);

BUG_ON(sparc_cpu_model != sun4m);
smp4m_smp_done();
}

void cpu_panic(void)
Expand All @@ -89,17 +101,6 @@ void cpu_panic(void)

struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };

void __init smp_boot_cpus(void)
{
extern void smp4m_boot_cpus(void);
extern void smp4d_boot_cpus(void);

if (sparc_cpu_model == sun4m)
smp4m_boot_cpus();
else
smp4d_boot_cpus();
}

void smp_send_reschedule(int cpu)
{
/* See sparc64 */
Expand Down Expand Up @@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier)
return 0;
}

void __init smp_prepare_cpus(unsigned int maxcpus)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
extern void smp4m_boot_cpus(void);
int i, cpuid, ncpus, extra;

BUG_ON(sparc_cpu_model != sun4m);
printk("Entering SMP Mode...\n");

ncpus = 1;
extra = 0;
for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
if (cpuid == boot_cpu_id)
continue;
if (cpuid < NR_CPUS && ncpus++ < max_cpus)
cpu_set(cpuid, phys_cpu_present_map);
else
extra++;
}
if (max_cpus >= NR_CPUS && extra)
printk("Warning: NR_CPUS is too low to start all cpus\n");

smp_store_cpu_info(boot_cpu_id);

smp4m_boot_cpus();
}

void __devinit smp_prepare_boot_cpu(void)
{
current_thread_info()->cpu = hard_smp_processor_id();
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), phys_cpu_present_map);
int cpuid = hard_smp_processor_id();

if (cpuid >= NR_CPUS) {
prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
prom_halt();
}
if (cpuid != 0)
printk("boot cpu id != 0, this could work but is untested\n");

current_thread_info()->cpu = cpuid;
cpu_set(cpuid, cpu_online_map);
cpu_set(cpuid, phys_cpu_present_map);
}

int __devinit __cpu_up(unsigned int cpu)
{
panic("smp doesn't work\n");
extern int smp4m_boot_one_cpu(int);
int ret;

ret = smp4m_boot_one_cpu(cpu);

if (!ret) {
cpu_set(cpu, smp_commenced_mask);
while (!cpu_online(cpu))
mb();
}
return ret;
}

void smp_bogo(struct seq_file *m)
Expand Down
4 changes: 0 additions & 4 deletions arch/sparc/kernel/sparc_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,6 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
/* IRQ implementation. */
EXPORT_SYMBOL(synchronize_irq);

/* Misc SMP information */
EXPORT_SYMBOL(__cpu_number_map);
EXPORT_SYMBOL(__cpu_logical_map);

/* CPU online map and active count. */
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map);
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/sun4d_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ unsigned char cpu_leds[32];
unsigned char sbus_tid[32];
#endif

extern struct irqaction *irq_action[];
static struct irqaction *irq_action[NR_IRQS];
extern spinlock_t irq_action_lock;

struct sbus_action {
Expand Down
8 changes: 5 additions & 3 deletions arch/sparc/kernel/sun4d_smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ extern volatile int smp_processors_ready;
extern int smp_num_cpus;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern struct cpuinfo_sparc cpu_data[NR_CPUS];
extern cpuinfo_sparc cpu_data[NR_CPUS];
extern unsigned char boot_cpu_id;
extern int smp_activated;
extern volatile int __cpu_number_map[NR_CPUS];
extern volatile int __cpu_logical_map[NR_CPUS];
extern volatile unsigned long ipi_count;
extern volatile int smp_process_available;
extern volatile int smp_commenced;

extern cpumask_t smp_commenced_mask;

extern int __smp4d_processor_id(void);

/* #define SMP_DEBUG */
Expand Down Expand Up @@ -136,7 +138,7 @@ void __init smp4d_callin(void)

local_irq_enable(); /* We don't allow PIL 14 yet */

while(!smp_commenced)
while (!cpu_isset(cpuid, smp_commenced_mask))
barrier();

spin_lock_irqsave(&sun4d_imsk_lock, flags);
Expand Down
Loading

0 comments on commit d71eecf

Please sign in to comment.