aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-05 16:30:23 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-05 16:30:23 -0400
commitfabb5c4e4a474ff0f7d6c1d3466a1b79bbce5f49 (patch)
treec77845e116145fe4e5f172c39f4da2f87b8476ce
parentaa12b2842aba8cc367a2e1ddb5c6ae4fd8ddb1da (diff)
parentd6444514b89098284099c17b9f168ef6236d3e8f (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/voyager-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/voyager-2.6: [VOYAGER] add smp alternatives [VOYAGER] Use modern techniques to setup and teardown low identiy mappings. [VOYAGER] Convert the monitor thread to use the kthread API [VOYAGER] clockevents driver: bring voyager in to line [VOYAGER] clockevents: correct boot cpu is zero assumption [VOYAGER] add smp_call_function_single
-rw-r--r--arch/i386/kernel/i8253.c2
-rw-r--r--arch/i386/mach-voyager/setup.c8
-rw-r--r--arch/i386/mach-voyager/voyager_cat.c4
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c97
-rw-r--r--arch/i386/mach-voyager/voyager_thread.c69
-rw-r--r--include/asm-i386/voyager.h6
6 files changed, 84 insertions, 102 deletions
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
index 10cef5ca8a5b..f8a3c4054c70 100644
--- a/arch/i386/kernel/i8253.c
+++ b/arch/i386/kernel/i8253.c
@@ -110,7 +110,7 @@ void __init setup_pit_timer(void)
110 * Start pit with the boot cpu mask and make it global after the 110 * Start pit with the boot cpu mask and make it global after the
111 * IO_APIC has been initialized. 111 * IO_APIC has been initialized.
112 */ 112 */
113 pit_clockevent.cpumask = cpumask_of_cpu(0); 113 pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
114 pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32); 114 pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
115 pit_clockevent.max_delta_ns = 115 pit_clockevent.max_delta_ns =
116 clockevent_delta2ns(0x7FFF, &pit_clockevent); 116 clockevent_delta2ns(0x7FFF, &pit_clockevent);
diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c
index cfa16c151c8f..447bb105cf58 100644
--- a/arch/i386/mach-voyager/setup.c
+++ b/arch/i386/mach-voyager/setup.c
@@ -40,10 +40,16 @@ void __init trap_init_hook(void)
40{ 40{
41} 41}
42 42
43static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; 43static struct irqaction irq0 = {
44 .handler = timer_interrupt,
45 .flags = IRQF_DISABLED | IRQF_NOBALANCING,
46 .mask = CPU_MASK_NONE,
47 .name = "timer"
48};
44 49
45void __init time_init_hook(void) 50void __init time_init_hook(void)
46{ 51{
52 irq0.mask = cpumask_of_cpu(safe_smp_processor_id());
47 setup_irq(0, &irq0); 53 setup_irq(0, &irq0);
48} 54}
49 55
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 943a9473b138..26a2d4c54b68 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -1111,7 +1111,7 @@ voyager_cat_do_common_interrupt(void)
1111 printk(KERN_ERR "Voyager front panel switch turned off\n"); 1111 printk(KERN_ERR "Voyager front panel switch turned off\n");
1112 voyager_status.switch_off = 1; 1112 voyager_status.switch_off = 1;
1113 voyager_status.request_from_kernel = 1; 1113 voyager_status.request_from_kernel = 1;
1114 up(&kvoyagerd_sem); 1114 wake_up_process(voyager_thread);
1115 } 1115 }
1116 /* Tell the hardware we're taking care of the 1116 /* Tell the hardware we're taking care of the
1117 * shutdown, otherwise it will power the box off 1117 * shutdown, otherwise it will power the box off
@@ -1157,7 +1157,7 @@ voyager_cat_do_common_interrupt(void)
1157 outb(VOYAGER_CAT_END, CAT_CMD); 1157 outb(VOYAGER_CAT_END, CAT_CMD);
1158 voyager_status.power_fail = 1; 1158 voyager_status.power_fail = 1;
1159 voyager_status.request_from_kernel = 1; 1159 voyager_status.request_from_kernel = 1;
1160 up(&kvoyagerd_sem); 1160 wake_up_process(voyager_thread);
1161 } 1161 }
1162 1162
1163 1163
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 74aeedf277f4..fe0ed393294c 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -536,15 +536,6 @@ do_boot_cpu(__u8 cpu)
536 & ~( voyager_extended_vic_processors 536 & ~( voyager_extended_vic_processors
537 & voyager_allowed_boot_processors); 537 & voyager_allowed_boot_processors);
538 538
539 /* For the 486, we can't use the 4Mb page table trick, so
540 * must map a region of memory */
541#ifdef CONFIG_M486
542 int i;
543 unsigned long *page_table_copies = (unsigned long *)
544 __get_free_page(GFP_KERNEL);
545#endif
546 pgd_t orig_swapper_pg_dir0;
547
548 /* This is an area in head.S which was used to set up the 539 /* This is an area in head.S which was used to set up the
549 * initial kernel stack. We need to alter this to give the 540 * initial kernel stack. We need to alter this to give the
550 * booting CPU a new stack (taken from its idle process) */ 541 * booting CPU a new stack (taken from its idle process) */
@@ -573,6 +564,8 @@ do_boot_cpu(__u8 cpu)
573 hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF; 564 hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
574 565
575 cpucount++; 566 cpucount++;
567 alternatives_smp_switch(1);
568
576 idle = fork_idle(cpu); 569 idle = fork_idle(cpu);
577 if(IS_ERR(idle)) 570 if(IS_ERR(idle))
578 panic("failed fork for CPU%d", cpu); 571 panic("failed fork for CPU%d", cpu);
@@ -595,24 +588,11 @@ do_boot_cpu(__u8 cpu)
595 VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, 588 VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu,
596 (unsigned long)hijack_source.val, hijack_source.idt.Segment, 589 (unsigned long)hijack_source.val, hijack_source.idt.Segment,
597 hijack_source.idt.Offset, stack_start.esp)); 590 hijack_source.idt.Offset, stack_start.esp));
598 /* set the original swapper_pg_dir[0] to map 0 to 4Mb transparently 591
599 * (so that the booting CPU can find start_32 */ 592 /* init lowmem identity mapping */
600 orig_swapper_pg_dir0 = swapper_pg_dir[0]; 593 clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
601#ifdef CONFIG_M486 594 min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
602 if(page_table_copies == NULL) 595 flush_tlb_all();
603 panic("No free memory for 486 page tables\n");
604 for(i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++)
605 page_table_copies[i] = (i * PAGE_SIZE)
606 | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
607
608 ((unsigned long *)swapper_pg_dir)[0] =
609 ((virt_to_phys(page_table_copies)) & PAGE_MASK)
610 | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
611#else
612 ((unsigned long *)swapper_pg_dir)[0] =
613 (virt_to_phys(pg0) & PAGE_MASK)
614 | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
615#endif
616 596
617 if(quad_boot) { 597 if(quad_boot) {
618 printk("CPU %d: non extended Quad boot\n", cpu); 598 printk("CPU %d: non extended Quad boot\n", cpu);
@@ -655,11 +635,7 @@ do_boot_cpu(__u8 cpu)
655 udelay(100); 635 udelay(100);
656 } 636 }
657 /* reset the page table */ 637 /* reset the page table */
658 swapper_pg_dir[0] = orig_swapper_pg_dir0; 638 zap_low_mappings();
659 local_flush_tlb();
660#ifdef CONFIG_M486
661 free_page((unsigned long)page_table_copies);
662#endif
663 639
664 if (cpu_booted_map) { 640 if (cpu_booted_map) {
665 VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n", 641 VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n",
@@ -1082,20 +1058,11 @@ smp_call_function_interrupt(void)
1082 } 1058 }
1083} 1059}
1084 1060
1085/* Call this function on all CPUs using the function_interrupt above 1061static int
1086 <func> The function to run. This must be fast and non-blocking. 1062__smp_call_function_mask (void (*func) (void *info), void *info, int retry,
1087 <info> An arbitrary pointer to pass to the function. 1063 int wait, __u32 mask)
1088 <retry> If true, keep retrying until ready.
1089 <wait> If true, wait until function has completed on other CPUs.
1090 [RETURNS] 0 on success, else a negative status code. Does not return until
1091 remote CPUs are nearly ready to execute <<func>> or are or have executed.
1092*/
1093int
1094smp_call_function (void (*func) (void *info), void *info, int retry,
1095 int wait)
1096{ 1064{
1097 struct call_data_struct data; 1065 struct call_data_struct data;
1098 __u32 mask = cpus_addr(cpu_online_map)[0];
1099 1066
1100 mask &= ~(1<<smp_processor_id()); 1067 mask &= ~(1<<smp_processor_id());
1101 1068
@@ -1116,7 +1083,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
1116 call_data = &data; 1083 call_data = &data;
1117 wmb(); 1084 wmb();
1118 /* Send a message to all other CPUs and wait for them to respond */ 1085 /* Send a message to all other CPUs and wait for them to respond */
1119 send_CPI_allbutself(VIC_CALL_FUNCTION_CPI); 1086 send_CPI(mask, VIC_CALL_FUNCTION_CPI);
1120 1087
1121 /* Wait for response */ 1088 /* Wait for response */
1122 while (data.started) 1089 while (data.started)
@@ -1130,8 +1097,48 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
1130 1097
1131 return 0; 1098 return 0;
1132} 1099}
1100
1101/* Call this function on all CPUs using the function_interrupt above
1102 <func> The function to run. This must be fast and non-blocking.
1103 <info> An arbitrary pointer to pass to the function.
1104 <retry> If true, keep retrying until ready.
1105 <wait> If true, wait until function has completed on other CPUs.
1106 [RETURNS] 0 on success, else a negative status code. Does not return until
1107 remote CPUs are nearly ready to execute <<func>> or are or have executed.
1108*/
1109int
1110smp_call_function(void (*func) (void *info), void *info, int retry,
1111 int wait)
1112{
1113 __u32 mask = cpus_addr(cpu_online_map)[0];
1114
1115 return __smp_call_function_mask(func, info, retry, wait, mask);
1116}
1133EXPORT_SYMBOL(smp_call_function); 1117EXPORT_SYMBOL(smp_call_function);
1134 1118
1119/*
1120 * smp_call_function_single - Run a function on another CPU
1121 * @func: The function to run. This must be fast and non-blocking.
1122 * @info: An arbitrary pointer to pass to the function.
1123 * @nonatomic: Currently unused.
1124 * @wait: If true, wait until function has completed on other CPUs.
1125 *
1126 * Retrurns 0 on success, else a negative status code.
1127 *
1128 * Does not return until the remote CPU is nearly ready to execute <func>
1129 * or is or has executed.
1130 */
1131
1132int
1133smp_call_function_single(int cpu, void (*func) (void *info), void *info,
1134 int nonatomic, int wait)
1135{
1136 __u32 mask = 1 << cpu;
1137
1138 return __smp_call_function_mask(func, info, nonatomic, wait, mask);
1139}
1140EXPORT_SYMBOL(smp_call_function_single);
1141
1135/* Sorry about the name. In an APIC based system, the APICs 1142/* Sorry about the name. In an APIC based system, the APICs
1136 * themselves are programmed to send a timer interrupt. This is used 1143 * themselves are programmed to send a timer interrupt. This is used
1137 * by linux to reschedule the processor. Voyager doesn't have this, 1144 * by linux to reschedule the processor. Voyager doesn't have this,
diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
index f39887359e8e..fdc1d926fb2a 100644
--- a/arch/i386/mach-voyager/voyager_thread.c
+++ b/arch/i386/mach-voyager/voyager_thread.c
@@ -24,33 +24,16 @@
24#include <linux/kmod.h> 24#include <linux/kmod.h>
25#include <linux/completion.h> 25#include <linux/completion.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27#include <linux/kthread.h>
27#include <asm/desc.h> 28#include <asm/desc.h>
28#include <asm/voyager.h> 29#include <asm/voyager.h>
29#include <asm/vic.h> 30#include <asm/vic.h>
30#include <asm/mtrr.h> 31#include <asm/mtrr.h>
31#include <asm/msr.h> 32#include <asm/msr.h>
32 33
33#define THREAD_NAME "kvoyagerd"
34 34
35/* external variables */ 35struct task_struct *voyager_thread;
36int kvoyagerd_running = 0; 36static __u8 set_timeout;
37DECLARE_MUTEX_LOCKED(kvoyagerd_sem);
38
39static int thread(void *);
40
41static __u8 set_timeout = 0;
42
43/* Start the machine monitor thread. Return 1 if OK, 0 if fail */
44static int __init
45voyager_thread_start(void)
46{
47 if(kernel_thread(thread, NULL, CLONE_KERNEL) < 0) {
48 /* This is serious, but not fatal */
49 printk(KERN_ERR "Voyager: Failed to create system monitor thread!!!\n");
50 return 1;
51 }
52 return 0;
53}
54 37
55static int 38static int
56execute(const char *string) 39execute(const char *string)
@@ -110,31 +93,15 @@ check_continuing_condition(void)
110 } 93 }
111} 94}
112 95
113static void
114wakeup(unsigned long unused)
115{
116 up(&kvoyagerd_sem);
117}
118
119static int 96static int
120thread(void *unused) 97thread(void *unused)
121{ 98{
122 struct timer_list wakeup_timer;
123
124 kvoyagerd_running = 1;
125
126 daemonize(THREAD_NAME);
127
128 set_timeout = 0;
129
130 init_timer(&wakeup_timer);
131
132 sigfillset(&current->blocked);
133
134 printk(KERN_NOTICE "Voyager starting monitor thread\n"); 99 printk(KERN_NOTICE "Voyager starting monitor thread\n");
135 100
136 for(;;) { 101 for (;;) {
137 down_interruptible(&kvoyagerd_sem); 102 set_current_state(TASK_INTERRUPTIBLE);
103 schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT);
104
138 VDEBUG(("Voyager Daemon awoken\n")); 105 VDEBUG(("Voyager Daemon awoken\n"));
139 if(voyager_status.request_from_kernel == 0) { 106 if(voyager_status.request_from_kernel == 0) {
140 /* probably awoken from timeout */ 107 /* probably awoken from timeout */
@@ -143,20 +110,26 @@ thread(void *unused)
143 check_from_kernel(); 110 check_from_kernel();
144 voyager_status.request_from_kernel = 0; 111 voyager_status.request_from_kernel = 0;
145 } 112 }
146 if(set_timeout) {
147 del_timer(&wakeup_timer);
148 wakeup_timer.expires = HZ + jiffies;
149 wakeup_timer.function = wakeup;
150 add_timer(&wakeup_timer);
151 }
152 } 113 }
153} 114}
154 115
116static int __init
117voyager_thread_start(void)
118{
119 voyager_thread = kthread_run(thread, NULL, "kvoyagerd");
120 if (IS_ERR(voyager_thread)) {
121 printk(KERN_ERR "Voyager: Failed to create system monitor thread.\n");
122 return PTR_ERR(voyager_thread);
123 }
124 return 0;
125}
126
127
155static void __exit 128static void __exit
156voyager_thread_stop(void) 129voyager_thread_stop(void)
157{ 130{
158 /* FIXME: do nothing at the moment */ 131 kthread_stop(voyager_thread);
159} 132}
160 133
161module_init(voyager_thread_start); 134module_init(voyager_thread_start);
162//module_exit(voyager_thread_stop); 135module_exit(voyager_thread_stop);
diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h
index 5b27838905b2..91a9932937ab 100644
--- a/include/asm-i386/voyager.h
+++ b/include/asm-i386/voyager.h
@@ -487,15 +487,11 @@ extern struct voyager_qic_cpi *voyager_quad_cpi_addr[NR_CPUS];
487extern struct voyager_SUS *voyager_SUS; 487extern struct voyager_SUS *voyager_SUS;
488 488
489/* variables exported always */ 489/* variables exported always */
490extern struct task_struct *voyager_thread;
490extern int voyager_level; 491extern int voyager_level;
491extern int kvoyagerd_running;
492extern struct semaphore kvoyagerd_sem;
493extern struct voyager_status voyager_status; 492extern struct voyager_status voyager_status;
494 493
495
496
497/* functions exported by the voyager and voyager_smp modules */ 494/* functions exported by the voyager and voyager_smp modules */
498
499extern int voyager_cat_readb(__u8 module, __u8 asic, int reg); 495extern int voyager_cat_readb(__u8 module, __u8 asic, int reg);
500extern void voyager_cat_init(void); 496extern void voyager_cat_init(void);
501extern void voyager_detect(struct voyager_bios_info *); 497extern void voyager_detect(struct voyager_bios_info *);