diff options
Diffstat (limited to 'arch/parisc/kernel/smp.c')
-rw-r--r-- | arch/parisc/kernel/smp.c | 178 |
1 files changed, 23 insertions, 155 deletions
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 12cc019307ad..6ba9257fdb7f 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c | |||
@@ -16,9 +16,6 @@ | |||
16 | ** the Free Software Foundation; either version 2 of the License, or | 16 | ** the Free Software Foundation; either version 2 of the License, or |
17 | ** (at your option) any later version. | 17 | ** (at your option) any later version. |
18 | */ | 18 | */ |
19 | #undef ENTRY_SYS_CPUS /* syscall support for iCOD-like functionality */ | ||
20 | |||
21 | |||
22 | #include <linux/types.h> | 19 | #include <linux/types.h> |
23 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
24 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -51,7 +48,15 @@ | |||
51 | #include <asm/unistd.h> | 48 | #include <asm/unistd.h> |
52 | #include <asm/cacheflush.h> | 49 | #include <asm/cacheflush.h> |
53 | 50 | ||
54 | #define kDEBUG 0 | 51 | #undef DEBUG_SMP |
52 | #ifdef DEBUG_SMP | ||
53 | static int smp_debug_lvl = 0; | ||
54 | #define smp_debug(lvl, printargs...) \ | ||
55 | if (lvl >= smp_debug_lvl) \ | ||
56 | printk(printargs); | ||
57 | #else | ||
58 | #define smp_debug(lvl, ...) | ||
59 | #endif /* DEBUG_SMP */ | ||
55 | 60 | ||
56 | DEFINE_SPINLOCK(smp_lock); | 61 | DEFINE_SPINLOCK(smp_lock); |
57 | 62 | ||
@@ -76,6 +81,7 @@ cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; /* Bitmap of Present CP | |||
76 | EXPORT_SYMBOL(cpu_online_map); | 81 | EXPORT_SYMBOL(cpu_online_map); |
77 | EXPORT_SYMBOL(cpu_possible_map); | 82 | EXPORT_SYMBOL(cpu_possible_map); |
78 | 83 | ||
84 | DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED; | ||
79 | 85 | ||
80 | struct smp_call_struct { | 86 | struct smp_call_struct { |
81 | void (*func) (void *info); | 87 | void (*func) (void *info); |
@@ -107,13 +113,6 @@ enum ipi_message_type { | |||
107 | static void | 113 | static void |
108 | ipi_init(int cpuid) | 114 | ipi_init(int cpuid) |
109 | { | 115 | { |
110 | |||
111 | /* If CPU is present ... */ | ||
112 | #ifdef ENTRY_SYS_CPUS | ||
113 | /* *and* running (not stopped) ... */ | ||
114 | #error iCOD support wants state checked here. | ||
115 | #endif | ||
116 | |||
117 | #error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region | 116 | #error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region |
118 | 117 | ||
119 | if(cpu_online(cpuid) ) | 118 | if(cpu_online(cpuid) ) |
@@ -133,23 +132,12 @@ ipi_init(int cpuid) | |||
133 | static void | 132 | static void |
134 | halt_processor(void) | 133 | halt_processor(void) |
135 | { | 134 | { |
136 | #ifdef ENTRY_SYS_CPUS | ||
137 | #error halt_processor() needs rework | ||
138 | /* | ||
139 | ** o migrate I/O interrupts off this CPU. | ||
140 | ** o leave IPI enabled - __cli() will disable IPI. | ||
141 | ** o leave CPU in online map - just change the state | ||
142 | */ | ||
143 | cpu_data[this_cpu].state = STATE_STOPPED; | ||
144 | mark_bh(IPI_BH); | ||
145 | #else | ||
146 | /* REVISIT : redirect I/O Interrupts to another CPU? */ | 135 | /* REVISIT : redirect I/O Interrupts to another CPU? */ |
147 | /* REVISIT : does PM *know* this CPU isn't available? */ | 136 | /* REVISIT : does PM *know* this CPU isn't available? */ |
148 | cpu_clear(smp_processor_id(), cpu_online_map); | 137 | cpu_clear(smp_processor_id(), cpu_online_map); |
149 | local_irq_disable(); | 138 | local_irq_disable(); |
150 | for (;;) | 139 | for (;;) |
151 | ; | 140 | ; |
152 | #endif | ||
153 | } | 141 | } |
154 | 142 | ||
155 | 143 | ||
@@ -167,10 +155,11 @@ ipi_interrupt(int irq, void *dev_id) | |||
167 | mb(); /* Order interrupt and bit testing. */ | 155 | mb(); /* Order interrupt and bit testing. */ |
168 | 156 | ||
169 | for (;;) { | 157 | for (;;) { |
170 | spin_lock_irqsave(&(p->lock),flags); | 158 | spinlock_t *lock = &per_cpu(ipi_lock, this_cpu); |
159 | spin_lock_irqsave(lock, flags); | ||
171 | ops = p->pending_ipi; | 160 | ops = p->pending_ipi; |
172 | p->pending_ipi = 0; | 161 | p->pending_ipi = 0; |
173 | spin_unlock_irqrestore(&(p->lock),flags); | 162 | spin_unlock_irqrestore(lock, flags); |
174 | 163 | ||
175 | mb(); /* Order bit clearing and data access. */ | 164 | mb(); /* Order bit clearing and data access. */ |
176 | 165 | ||
@@ -184,15 +173,11 @@ ipi_interrupt(int irq, void *dev_id) | |||
184 | 173 | ||
185 | switch (which) { | 174 | switch (which) { |
186 | case IPI_NOP: | 175 | case IPI_NOP: |
187 | #if (kDEBUG>=100) | 176 | smp_debug(100, KERN_DEBUG "CPU%d IPI_NOP\n", this_cpu); |
188 | printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu); | ||
189 | #endif /* kDEBUG */ | ||
190 | break; | 177 | break; |
191 | 178 | ||
192 | case IPI_RESCHEDULE: | 179 | case IPI_RESCHEDULE: |
193 | #if (kDEBUG>=100) | 180 | smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); |
194 | printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); | ||
195 | #endif /* kDEBUG */ | ||
196 | /* | 181 | /* |
197 | * Reschedule callback. Everything to be | 182 | * Reschedule callback. Everything to be |
198 | * done is done by the interrupt return path. | 183 | * done is done by the interrupt return path. |
@@ -200,9 +185,7 @@ ipi_interrupt(int irq, void *dev_id) | |||
200 | break; | 185 | break; |
201 | 186 | ||
202 | case IPI_CALL_FUNC: | 187 | case IPI_CALL_FUNC: |
203 | #if (kDEBUG>=100) | 188 | smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC\n", this_cpu); |
204 | printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); | ||
205 | #endif /* kDEBUG */ | ||
206 | { | 189 | { |
207 | volatile struct smp_call_struct *data; | 190 | volatile struct smp_call_struct *data; |
208 | void (*func)(void *info); | 191 | void (*func)(void *info); |
@@ -233,28 +216,16 @@ ipi_interrupt(int irq, void *dev_id) | |||
233 | break; | 216 | break; |
234 | 217 | ||
235 | case IPI_CPU_START: | 218 | case IPI_CPU_START: |
236 | #if (kDEBUG>=100) | 219 | smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu); |
237 | printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); | ||
238 | #endif /* kDEBUG */ | ||
239 | #ifdef ENTRY_SYS_CPUS | ||
240 | p->state = STATE_RUNNING; | ||
241 | #endif | ||
242 | break; | 220 | break; |
243 | 221 | ||
244 | case IPI_CPU_STOP: | 222 | case IPI_CPU_STOP: |
245 | #if (kDEBUG>=100) | 223 | smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_STOP\n", this_cpu); |
246 | printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); | ||
247 | #endif /* kDEBUG */ | ||
248 | #ifdef ENTRY_SYS_CPUS | ||
249 | #else | ||
250 | halt_processor(); | 224 | halt_processor(); |
251 | #endif | ||
252 | break; | 225 | break; |
253 | 226 | ||
254 | case IPI_CPU_TEST: | 227 | case IPI_CPU_TEST: |
255 | #if (kDEBUG>=100) | 228 | smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu); |
256 | printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); | ||
257 | #endif /* kDEBUG */ | ||
258 | break; | 229 | break; |
259 | 230 | ||
260 | default: | 231 | default: |
@@ -275,12 +246,13 @@ static inline void | |||
275 | ipi_send(int cpu, enum ipi_message_type op) | 246 | ipi_send(int cpu, enum ipi_message_type op) |
276 | { | 247 | { |
277 | struct cpuinfo_parisc *p = &cpu_data[cpu]; | 248 | struct cpuinfo_parisc *p = &cpu_data[cpu]; |
249 | spinlock_t *lock = &per_cpu(ipi_lock, cpu); | ||
278 | unsigned long flags; | 250 | unsigned long flags; |
279 | 251 | ||
280 | spin_lock_irqsave(&(p->lock),flags); | 252 | spin_lock_irqsave(lock, flags); |
281 | p->pending_ipi |= 1 << op; | 253 | p->pending_ipi |= 1 << op; |
282 | gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa); | 254 | gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa); |
283 | spin_unlock_irqrestore(&(p->lock),flags); | 255 | spin_unlock_irqrestore(lock, flags); |
284 | } | 256 | } |
285 | 257 | ||
286 | 258 | ||
@@ -560,13 +532,8 @@ int __init smp_boot_one_cpu(int cpuid) | |||
560 | 532 | ||
561 | alive: | 533 | alive: |
562 | /* Remember the Slave data */ | 534 | /* Remember the Slave data */ |
563 | #if (kDEBUG>=100) | 535 | smp_debug(100, KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n", |
564 | printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n", | ||
565 | cpuid, timeout * 100); | 536 | cpuid, timeout * 100); |
566 | #endif /* kDEBUG */ | ||
567 | #ifdef ENTRY_SYS_CPUS | ||
568 | cpu_data[cpuid].state = STATE_RUNNING; | ||
569 | #endif | ||
570 | return 0; | 537 | return 0; |
571 | } | 538 | } |
572 | 539 | ||
@@ -574,10 +541,6 @@ void __devinit smp_prepare_boot_cpu(void) | |||
574 | { | 541 | { |
575 | int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ | 542 | int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ |
576 | 543 | ||
577 | #ifdef ENTRY_SYS_CPUS | ||
578 | cpu_data[0].state = STATE_RUNNING; | ||
579 | #endif | ||
580 | |||
581 | /* Setup BSP mappings */ | 544 | /* Setup BSP mappings */ |
582 | printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor); | 545 | printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor); |
583 | 546 | ||
@@ -616,101 +579,6 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
616 | return cpu_online(cpu) ? 0 : -ENOSYS; | 579 | return cpu_online(cpu) ? 0 : -ENOSYS; |
617 | } | 580 | } |
618 | 581 | ||
619 | |||
620 | |||
621 | #ifdef ENTRY_SYS_CPUS | ||
622 | /* Code goes along with: | ||
623 | ** entry.s: ENTRY_NAME(sys_cpus) / * 215, for cpu stat * / | ||
624 | */ | ||
625 | int sys_cpus(int argc, char **argv) | ||
626 | { | ||
627 | int i,j=0; | ||
628 | extern int current_pid(int cpu); | ||
629 | |||
630 | if( argc > 2 ) { | ||
631 | printk("sys_cpus:Only one argument supported\n"); | ||
632 | return (-1); | ||
633 | } | ||
634 | if ( argc == 1 ){ | ||
635 | |||
636 | #ifdef DUMP_MORE_STATE | ||
637 | for_each_online_cpu(i) { | ||
638 | int cpus_per_line = 4; | ||
639 | |||
640 | if (j++ % cpus_per_line) | ||
641 | printk(" %3d",i); | ||
642 | else | ||
643 | printk("\n %3d",i); | ||
644 | } | ||
645 | printk("\n"); | ||
646 | #else | ||
647 | printk("\n 0\n"); | ||
648 | #endif | ||
649 | } else if((argc==2) && !(strcmp(argv[1],"-l"))) { | ||
650 | printk("\nCPUSTATE TASK CPUNUM CPUID HARDCPU(HPA)\n"); | ||
651 | #ifdef DUMP_MORE_STATE | ||
652 | for_each_online_cpu(i) { | ||
653 | if (cpu_data[i].cpuid != NO_PROC_ID) { | ||
654 | switch(cpu_data[i].state) { | ||
655 | case STATE_RENDEZVOUS: | ||
656 | printk("RENDEZVS "); | ||
657 | break; | ||
658 | case STATE_RUNNING: | ||
659 | printk((current_pid(i)!=0) ? "RUNNING " : "IDLING "); | ||
660 | break; | ||
661 | case STATE_STOPPED: | ||
662 | printk("STOPPED "); | ||
663 | break; | ||
664 | case STATE_HALTED: | ||
665 | printk("HALTED "); | ||
666 | break; | ||
667 | default: | ||
668 | printk("%08x?", cpu_data[i].state); | ||
669 | break; | ||
670 | } | ||
671 | if(cpu_online(i)) { | ||
672 | printk(" %4d",current_pid(i)); | ||
673 | } | ||
674 | printk(" %6d",cpu_number_map(i)); | ||
675 | printk(" %5d",i); | ||
676 | printk(" 0x%lx\n",cpu_data[i].hpa); | ||
677 | } | ||
678 | } | ||
679 | #else | ||
680 | printk("\n%s %4d 0 0 --------", | ||
681 | (current->pid)?"RUNNING ": "IDLING ",current->pid); | ||
682 | #endif | ||
683 | } else if ((argc==2) && !(strcmp(argv[1],"-s"))) { | ||
684 | #ifdef DUMP_MORE_STATE | ||
685 | printk("\nCPUSTATE CPUID\n"); | ||
686 | for_each_online_cpu(i) { | ||
687 | if (cpu_data[i].cpuid != NO_PROC_ID) { | ||
688 | switch(cpu_data[i].state) { | ||
689 | case STATE_RENDEZVOUS: | ||
690 | printk("RENDEZVS");break; | ||
691 | case STATE_RUNNING: | ||
692 | printk((current_pid(i)!=0) ? "RUNNING " : "IDLING"); | ||
693 | break; | ||
694 | case STATE_STOPPED: | ||
695 | printk("STOPPED ");break; | ||
696 | case STATE_HALTED: | ||
697 | printk("HALTED ");break; | ||
698 | default: | ||
699 | } | ||
700 | printk(" %5d\n",i); | ||
701 | } | ||
702 | } | ||
703 | #else | ||
704 | printk("\n%s CPU0",(current->pid==0)?"RUNNING ":"IDLING "); | ||
705 | #endif | ||
706 | } else { | ||
707 | printk("sys_cpus:Unknown request\n"); | ||
708 | return (-1); | ||
709 | } | ||
710 | return 0; | ||
711 | } | ||
712 | #endif /* ENTRY_SYS_CPUS */ | ||
713 | |||
714 | #ifdef CONFIG_PROC_FS | 582 | #ifdef CONFIG_PROC_FS |
715 | int __init | 583 | int __init |
716 | setup_profiling_timer(unsigned int multiplier) | 584 | setup_profiling_timer(unsigned int multiplier) |