From 18404756765c713a0be4eb1082920c04822ce588 Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Thu, 29 May 2008 11:02:52 -0700 Subject: genirq: Expose default irq affinity mask (take 3) Current IRQ affinity interface does not provide a way to set affinity for the IRQs that will be allocated/activated in the future. This patch creates /proc/irq/default_smp_affinity that lets users set default affinity mask for the newly allocated IRQs. Changing the default does not affect affinity masks for the currently active IRQs, they have to be changed explicitly. Updated based on Paul J's comments and added some more documentation. Signed-off-by: Max Krasnyansky Cc: pj@sgi.com Cc: a.p.zijlstra@chello.nl Cc: tglx@linutronix.de Cc: rdunlap@xenotime.net Cc: mingo@elte.hu Signed-off-by: Thomas Gleixner --- arch/alpha/kernel/irq.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index facf82a5499a..c626a821cdcb 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -42,8 +42,7 @@ void ack_bad_irq(unsigned int irq) #ifdef CONFIG_SMP static char irq_user_affinity[NR_IRQS]; -int -select_smp_affinity(unsigned int irq) +int irq_select_affinity(unsigned int irq) { static int last_cpu; int cpu = last_cpu + 1; @@ -51,7 +50,7 @@ select_smp_affinity(unsigned int irq) if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq]) return 1; - while (!cpu_possible(cpu)) + while (!cpu_possible(cpu) || !cpu_isset(cpu, irq_default_affinity)) cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0); last_cpu = cpu; -- cgit v1.2.3 From c524a1d8914408fd57241d9542fa2d402f004a33 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 10 Jun 2008 20:47:29 +0200 Subject: alpha: convert to generic helpers for IPI function calls This converts alpha to use the new helpers for smp_call_function() and friends, and adds support for smp_call_function_single(). Signed-off-by: Jens Axboe --- arch/alpha/Kconfig | 1 + arch/alpha/kernel/core_marvel.c | 6 +- arch/alpha/kernel/smp.c | 170 +++------------------------------------- 3 files changed, 14 insertions(+), 163 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 729cdbdf8036..dbe8c280fea9 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -528,6 +528,7 @@ config ARCH_MAY_HAVE_PC_FDC config SMP bool "Symmetric multi-processing support" depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL + select USE_GENERIC_SMP_HELPERS ---help--- This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index b04f1feb1dda..ced4aae8b804 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -660,9 +660,9 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write) #ifdef CONFIG_SMP if (smp_processor_id() != boot_cpuid) - smp_call_function_on_cpu(__marvel_access_rtc, - &rtc_access, 1, 1, - cpumask_of_cpu(boot_cpuid)); + smp_call_function_single(boot_cpuid, + __marvel_access_rtc, + &rtc_access, 1, 1); else __marvel_access_rtc(&rtc_access); #else diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 2525692db0ab..95c905be9154 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -62,6 +62,7 @@ static struct { enum ipi_message_type { IPI_RESCHEDULE, IPI_CALL_FUNC, + IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, }; @@ -558,51 +559,6 @@ send_ipi_message(cpumask_t to_whom, enum ipi_message_type operation) wripir(i); } -/* Structure and data for smp_call_function. This is designed to - minimize static memory requirements. Plus it looks cleaner. */ - -struct smp_call_struct { - void (*func) (void *info); - void *info; - long wait; - atomic_t unstarted_count; - atomic_t unfinished_count; -}; - -static struct smp_call_struct *smp_call_function_data; - -/* Atomicly drop data into a shared pointer. The pointer is free if - it is initially locked. If retry, spin until free. */ - -static int -pointer_lock (void *lock, void *data, int retry) -{ - void *old, *tmp; - - mb(); - again: - /* Compare and swap with zero. */ - asm volatile ( - "1: ldq_l %0,%1\n" - " mov %3,%2\n" - " bne %0,2f\n" - " stq_c %2,%1\n" - " beq %2,1b\n" - "2:" - : "=&r"(old), "=m"(*(void **)lock), "=&r"(tmp) - : "r"(data) - : "memory"); - - if (old == 0) - return 0; - if (! retry) - return -EBUSY; - - while (*(void **)lock) - barrier(); - goto again; -} - void handle_ipi(struct pt_regs *regs) { @@ -632,31 +588,12 @@ handle_ipi(struct pt_regs *regs) break; case IPI_CALL_FUNC: - { - struct smp_call_struct *data; - void (*func)(void *info); - void *info; - int wait; - - data = smp_call_function_data; - func = data->func; - info = data->info; - wait = data->wait; - - /* Notify the sending CPU that the data has been - received, and execution is about to begin. */ - mb(); - atomic_dec (&data->unstarted_count); - - /* At this point the structure may be gone unless - wait is true. */ - (*func)(info); - - /* Notify the sending CPU that the task is done. */ - mb(); - if (wait) atomic_dec (&data->unfinished_count); + generic_smp_call_function_interrupt(); + break; + + case IPI_CALL_FUNC_SINGLE: + generic_smp_call_function_single_interrupt(); break; - } case IPI_CPU_STOP: halt(); @@ -700,102 +637,15 @@ smp_send_stop(void) send_ipi_message(to_whom, IPI_CPU_STOP); } -/* - * Run a function on all other CPUs. - * The function to run. This must be fast and non-blocking. - * An arbitrary pointer to pass to the function. - * If true, keep retrying until ready. - * 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 - * or are or have executed. - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ - -int -smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry, - int wait, cpumask_t to_whom) +void arch_send_call_function_ipi(cpumask_t mask) { - struct smp_call_struct data; - unsigned long timeout; - int num_cpus_to_call; - - /* Can deadlock when called with interrupts disabled */ - WARN_ON(irqs_disabled()); - - data.func = func; - data.info = info; - data.wait = wait; - - cpu_clear(smp_processor_id(), to_whom); - num_cpus_to_call = cpus_weight(to_whom); - - atomic_set(&data.unstarted_count, num_cpus_to_call); - atomic_set(&data.unfinished_count, num_cpus_to_call); - - /* Acquire the smp_call_function_data mutex. */ - if (pointer_lock(&smp_call_function_data, &data, retry)) - return -EBUSY; - - /* Send a message to the requested CPUs. */ - send_ipi_message(to_whom, IPI_CALL_FUNC); - - /* Wait for a minimal response. */ - timeout = jiffies + HZ; - while (atomic_read (&data.unstarted_count) > 0 - && time_before (jiffies, timeout)) - barrier(); - - /* If there's no response yet, log a message but allow a longer - * timeout period -- if we get a response this time, log - * a message saying when we got it.. - */ - if (atomic_read(&data.unstarted_count) > 0) { - long start_time = jiffies; - printk(KERN_ERR "%s: initial timeout -- trying long wait\n", - __func__); - timeout = jiffies + 30 * HZ; - while (atomic_read(&data.unstarted_count) > 0 - && time_before(jiffies, timeout)) - barrier(); - if (atomic_read(&data.unstarted_count) <= 0) { - long delta = jiffies - start_time; - printk(KERN_ERR - "%s: response %ld.%ld seconds into long wait\n", - __func__, delta / HZ, - (100 * (delta - ((delta / HZ) * HZ))) / HZ); - } - } - - /* We either got one or timed out -- clear the lock. */ - mb(); - smp_call_function_data = NULL; - - /* - * If after both the initial and long timeout periods we still don't - * have a response, something is very wrong... - */ - BUG_ON(atomic_read (&data.unstarted_count) > 0); - - /* Wait for a complete response, if needed. */ - if (wait) { - while (atomic_read (&data.unfinished_count) > 0) - barrier(); - } - - return 0; + send_ipi_message(mask, IPI_CALL_FUNC); } -EXPORT_SYMBOL(smp_call_function_on_cpu); -int -smp_call_function (void (*func) (void *info), void *info, int retry, int wait) +void arch_send_call_function_single_ipi(int cpu) { - return smp_call_function_on_cpu (func, info, retry, wait, - cpu_online_map); + send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE); } -EXPORT_SYMBOL(smp_call_function); static void ipi_imb(void *ignored) -- cgit v1.2.3 From 8691e5a8f691cc2a4fda0651e8d307aaba0e7d68 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 6 Jun 2008 11:18:06 +0200 Subject: smp_call_function: get rid of the unused nonatomic/retry argument It's never used and the comments refer to nonatomic and retry interchangably. So get rid of it. Acked-by: Jeremy Fitzhardinge Signed-off-by: Jens Axboe --- arch/alpha/kernel/core_marvel.c | 2 +- arch/alpha/kernel/smp.c | 6 +++--- arch/alpha/oprofile/common.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index ced4aae8b804..04dcc5e5d4c1 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -662,7 +662,7 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write) if (smp_processor_id() != boot_cpuid) smp_call_function_single(boot_cpuid, __marvel_access_rtc, - &rtc_access, 1, 1); + &rtc_access, 1); else __marvel_access_rtc(&rtc_access); #else diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 95c905be9154..44114c8dbb2a 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -710,7 +710,7 @@ flush_tlb_mm(struct mm_struct *mm) } } - if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { + if (smp_call_function(ipi_flush_tlb_mm, mm, 1)) { printk(KERN_CRIT "flush_tlb_mm: timed out\n"); } @@ -763,7 +763,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) data.mm = mm; data.addr = addr; - if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) { + if (smp_call_function(ipi_flush_tlb_page, &data, 1)) { printk(KERN_CRIT "flush_tlb_page: timed out\n"); } @@ -815,7 +815,7 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page, } } - if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) { + if (smp_call_function(ipi_flush_icache_page, mm, 1)) { printk(KERN_CRIT "flush_icache_page: timed out\n"); } diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c index 9fc0eeb4f0ab..7c3d5ec6ec67 100644 --- a/arch/alpha/oprofile/common.c +++ b/arch/alpha/oprofile/common.c @@ -65,7 +65,7 @@ op_axp_setup(void) model->reg_setup(®, ctr, &sys); /* Configure the registers on all cpus. */ - (void)smp_call_function(model->cpu_setup, ®, 0, 1); + (void)smp_call_function(model->cpu_setup, ®, 1); model->cpu_setup(®); return 0; } @@ -86,7 +86,7 @@ op_axp_cpu_start(void *dummy) static int op_axp_start(void) { - (void)smp_call_function(op_axp_cpu_start, NULL, 0, 1); + (void)smp_call_function(op_axp_cpu_start, NULL, 1); op_axp_cpu_start(NULL); return 0; } @@ -101,7 +101,7 @@ op_axp_cpu_stop(void *dummy) static void op_axp_stop(void) { - (void)smp_call_function(op_axp_cpu_stop, NULL, 0, 1); + (void)smp_call_function(op_axp_cpu_stop, NULL, 1); op_axp_cpu_stop(NULL); } -- cgit v1.2.3 From 15c8b6c1aaaf1c4edd67e2f02e4d8e1bd1a51c0d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 9 May 2008 09:39:44 +0200 Subject: on_each_cpu(): kill unused 'retry' parameter It's not even passed on to smp_call_function() anymore, since that was removed. So kill it. Acked-by: Jeremy Fitzhardinge Reviewed-by: Paul E. McKenney Signed-off-by: Jens Axboe --- arch/alpha/kernel/process.c | 2 +- arch/alpha/kernel/smp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 96ed82fd9eef..351407e07e71 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -160,7 +160,7 @@ common_shutdown(int mode, char *restart_cmd) struct halt_info args; args.mode = mode; args.restart_cmd = restart_cmd; - on_each_cpu(common_shutdown_1, &args, 1, 0); + on_each_cpu(common_shutdown_1, &args, 0); } void diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 44114c8dbb2a..83df541650fc 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -657,7 +657,7 @@ void smp_imb(void) { /* Must wait other processors to flush their icache before continue. */ - if (on_each_cpu(ipi_imb, NULL, 1, 1)) + if (on_each_cpu(ipi_imb, NULL, 1)) printk(KERN_CRIT "smp_imb: timed out\n"); } EXPORT_SYMBOL(smp_imb); @@ -673,7 +673,7 @@ flush_tlb_all(void) { /* Although we don't have any data to pass, we do want to synchronize with the other processors. */ - if (on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1)) { + if (on_each_cpu(ipi_flush_tlb_all, NULL, 1)) { printk(KERN_CRIT "flush_tlb_all: timed out\n"); } } -- cgit v1.2.3