diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-05 13:30:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-05 13:30:23 -0700 |
commit | fabb5c4e4a474ff0f7d6c1d3466a1b79bbce5f49 (patch) | |
tree | c77845e116145fe4e5f172c39f4da2f87b8476ce | |
parent | aa12b2842aba8cc367a2e1ddb5c6ae4fd8ddb1da (diff) | |
parent | d6444514b89098284099c17b9f168ef6236d3e8f (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.c | 2 | ||||
-rw-r--r-- | arch/i386/mach-voyager/setup.c | 8 | ||||
-rw-r--r-- | arch/i386/mach-voyager/voyager_cat.c | 4 | ||||
-rw-r--r-- | arch/i386/mach-voyager/voyager_smp.c | 97 | ||||
-rw-r--r-- | arch/i386/mach-voyager/voyager_thread.c | 69 | ||||
-rw-r--r-- | include/asm-i386/voyager.h | 6 |
6 files changed, 84 insertions, 102 deletions
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c index 10cef5ca8a5..f8a3c4054c7 100644 --- a/arch/i386/kernel/i8253.c +++ b/arch/i386/kernel/i8253.c @@ -110,7 +110,7 @@ void __init setup_pit_timer(void) * Start pit with the boot cpu mask and make it global after the * IO_APIC has been initialized. */ - pit_clockevent.cpumask = cpumask_of_cpu(0); + pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32); pit_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFF, &pit_clockevent); diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c index cfa16c151c8..447bb105cf5 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) { } -static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq0 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED | IRQF_NOBALANCING, + .mask = CPU_MASK_NONE, + .name = "timer" +}; void __init time_init_hook(void) { + irq0.mask = cpumask_of_cpu(safe_smp_processor_id()); setup_irq(0, &irq0); } diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c index 943a9473b13..26a2d4c54b6 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) printk(KERN_ERR "Voyager front panel switch turned off\n"); voyager_status.switch_off = 1; voyager_status.request_from_kernel = 1; - up(&kvoyagerd_sem); + wake_up_process(voyager_thread); } /* Tell the hardware we're taking care of the * shutdown, otherwise it will power the box off @@ -1157,7 +1157,7 @@ voyager_cat_do_common_interrupt(void) outb(VOYAGER_CAT_END, CAT_CMD); voyager_status.power_fail = 1; voyager_status.request_from_kernel = 1; - up(&kvoyagerd_sem); + wake_up_process(voyager_thread); } diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 74aeedf277f..fe0ed393294 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) & ~( voyager_extended_vic_processors & voyager_allowed_boot_processors); - /* For the 486, we can't use the 4Mb page table trick, so - * must map a region of memory */ -#ifdef CONFIG_M486 - int i; - unsigned long *page_table_copies = (unsigned long *) - __get_free_page(GFP_KERNEL); -#endif - pgd_t orig_swapper_pg_dir0; - /* This is an area in head.S which was used to set up the * initial kernel stack. We need to alter this to give the * booting CPU a new stack (taken from its idle process) */ @@ -573,6 +564,8 @@ do_boot_cpu(__u8 cpu) hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF; cpucount++; + alternatives_smp_switch(1); + idle = fork_idle(cpu); if(IS_ERR(idle)) panic("failed fork for CPU%d", cpu); @@ -595,24 +588,11 @@ do_boot_cpu(__u8 cpu) VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, (unsigned long)hijack_source.val, hijack_source.idt.Segment, hijack_source.idt.Offset, stack_start.esp)); - /* set the original swapper_pg_dir[0] to map 0 to 4Mb transparently - * (so that the booting CPU can find start_32 */ - orig_swapper_pg_dir0 = swapper_pg_dir[0]; -#ifdef CONFIG_M486 - if(page_table_copies == NULL) - panic("No free memory for 486 page tables\n"); - for(i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++) - page_table_copies[i] = (i * PAGE_SIZE) - | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT; - - ((unsigned long *)swapper_pg_dir)[0] = - ((virt_to_phys(page_table_copies)) & PAGE_MASK) - | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT; -#else - ((unsigned long *)swapper_pg_dir)[0] = - (virt_to_phys(pg0) & PAGE_MASK) - | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT; -#endif + + /* init lowmem identity mapping */ + clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); + flush_tlb_all(); if(quad_boot) { printk("CPU %d: non extended Quad boot\n", cpu); @@ -655,11 +635,7 @@ do_boot_cpu(__u8 cpu) udelay(100); } /* reset the page table */ - swapper_pg_dir[0] = orig_swapper_pg_dir0; - local_flush_tlb(); -#ifdef CONFIG_M486 - free_page((unsigned long)page_table_copies); -#endif + zap_low_mappings(); if (cpu_booted_map) { VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n", @@ -1082,20 +1058,11 @@ smp_call_function_interrupt(void) } } -/* Call this function on all CPUs using the function_interrupt above - <func> The function to run. This must be fast and non-blocking. - <info> An arbitrary pointer to pass to the function. - <retry> If true, keep retrying until ready. - <wait> If true, wait until function has completed on other CPUs. - [RETURNS] 0 on success, else a negative status code. Does not return until - remote CPUs are nearly ready to execute <<func>> or are or have executed. -*/ -int -smp_call_function (void (*func) (void *info), void *info, int retry, - int wait) +static int +__smp_call_function_mask (void (*func) (void *info), void *info, int retry, + int wait, __u32 mask) { struct call_data_struct data; - __u32 mask = cpus_addr(cpu_online_map)[0]; mask &= ~(1<<smp_processor_id()); @@ -1116,7 +1083,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry, call_data = &data; wmb(); /* Send a message to all other CPUs and wait for them to respond */ - send_CPI_allbutself(VIC_CALL_FUNCTION_CPI); + send_CPI(mask, VIC_CALL_FUNCTION_CPI); /* Wait for response */ while (data.started) @@ -1130,8 +1097,48 @@ smp_call_function (void (*func) (void *info), void *info, int retry, return 0; } + +/* Call this function on all CPUs using the function_interrupt above + <func> The function to run. This must be fast and non-blocking. + <info> An arbitrary pointer to pass to the function. + <retry> If true, keep retrying until ready. + <wait> If true, wait until function has completed on other CPUs. + [RETURNS] 0 on success, else a negative status code. Does not return until + remote CPUs are nearly ready to execute <<func>> or are or have executed. +*/ +int +smp_call_function(void (*func) (void *info), void *info, int retry, + int wait) +{ + __u32 mask = cpus_addr(cpu_online_map)[0]; + + return __smp_call_function_mask(func, info, retry, wait, mask); +} EXPORT_SYMBOL(smp_call_function); +/* + * smp_call_function_single - Run a function on another CPU + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Currently unused. + * @wait: If true, wait until function has completed on other CPUs. + * + * Retrurns 0 on success, else a negative status code. + * + * Does not return until the remote CPU is nearly ready to execute <func> + * or is or has executed. + */ + +int +smp_call_function_single(int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + __u32 mask = 1 << cpu; + + return __smp_call_function_mask(func, info, nonatomic, wait, mask); +} +EXPORT_SYMBOL(smp_call_function_single); + /* Sorry about the name. In an APIC based system, the APICs * themselves are programmed to send a timer interrupt. This is used * 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 f39887359e8..fdc1d926fb2 100644 --- a/arch/i386/mach-voyager/voyager_thread.c +++ b/arch/i386/mach-voyager/voyager_thread.c @@ -24,33 +24,16 @@ #include <linux/kmod.h> #include <linux/completion.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <asm/desc.h> #include <asm/voyager.h> #include <asm/vic.h> #include <asm/mtrr.h> #include <asm/msr.h> -#define THREAD_NAME "kvoyagerd" -/* external variables */ -int kvoyagerd_running = 0; -DECLARE_MUTEX_LOCKED(kvoyagerd_sem); - -static int thread(void *); - -static __u8 set_timeout = 0; - -/* Start the machine monitor thread. Return 1 if OK, 0 if fail */ -static int __init -voyager_thread_start(void) -{ - if(kernel_thread(thread, NULL, CLONE_KERNEL) < 0) { - /* This is serious, but not fatal */ - printk(KERN_ERR "Voyager: Failed to create system monitor thread!!!\n"); - return 1; - } - return 0; -} +struct task_struct *voyager_thread; +static __u8 set_timeout; static int execute(const char *string) @@ -110,31 +93,15 @@ check_continuing_condition(void) } } -static void -wakeup(unsigned long unused) -{ - up(&kvoyagerd_sem); -} - static int thread(void *unused) { - struct timer_list wakeup_timer; - - kvoyagerd_running = 1; - - daemonize(THREAD_NAME); - - set_timeout = 0; - - init_timer(&wakeup_timer); - - sigfillset(¤t->blocked); - printk(KERN_NOTICE "Voyager starting monitor thread\n"); - for(;;) { - down_interruptible(&kvoyagerd_sem); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT); + VDEBUG(("Voyager Daemon awoken\n")); if(voyager_status.request_from_kernel == 0) { /* probably awoken from timeout */ @@ -143,20 +110,26 @@ thread(void *unused) check_from_kernel(); voyager_status.request_from_kernel = 0; } - if(set_timeout) { - del_timer(&wakeup_timer); - wakeup_timer.expires = HZ + jiffies; - wakeup_timer.function = wakeup; - add_timer(&wakeup_timer); - } } } +static int __init +voyager_thread_start(void) +{ + voyager_thread = kthread_run(thread, NULL, "kvoyagerd"); + if (IS_ERR(voyager_thread)) { + printk(KERN_ERR "Voyager: Failed to create system monitor thread.\n"); + return PTR_ERR(voyager_thread); + } + return 0; +} + + static void __exit voyager_thread_stop(void) { - /* FIXME: do nothing at the moment */ + kthread_stop(voyager_thread); } module_init(voyager_thread_start); -//module_exit(voyager_thread_stop); +module_exit(voyager_thread_stop); diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h index 5b27838905b..91a9932937a 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]; extern struct voyager_SUS *voyager_SUS; /* variables exported always */ +extern struct task_struct *voyager_thread; extern int voyager_level; -extern int kvoyagerd_running; -extern struct semaphore kvoyagerd_sem; extern struct voyager_status voyager_status; - - /* functions exported by the voyager and voyager_smp modules */ - extern int voyager_cat_readb(__u8 module, __u8 asic, int reg); extern void voyager_cat_init(void); extern void voyager_detect(struct voyager_bios_info *); |