Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fabb5c4e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents aa12b284 d6444514
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
+7 −1
Original line number Diff line number Diff line
@@ -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);
}

+2 −2
Original line number Diff line number Diff line
@@ -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);
		}
		
		
+52 −45
Original line number Diff line number Diff line
@@ -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,
+21 −48
Original line number Diff line number Diff line
@@ -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(&current->blocked);

	printk(KERN_NOTICE "Voyager starting monitor thread\n");

	for (;;) {
		down_interruptible(&kvoyagerd_sem);
		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);
Loading