From 66a062db4efcba3d63ff452464de9dede891f136 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 13 May 2007 11:55:14 -0400 Subject: [PATCH] --- yaml --- r: 56417 b: refs/heads/master c: 30046e5885848fe5c2c66177dca6b277323e31ab h: refs/heads/master i: 56415: 294b6ebb36a3628697c63e465696ddb15672a497 v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 3 +- trunk/arch/i386/kernel/Makefile | 1 - .../i386/kernel/cpu/cpufreq/powernow-k8.c | 2 +- .../i386/kernel/cpu/cpufreq/powernow-k8.h | 4 +- trunk/arch/i386/kernel/smp.c | 65 +- trunk/arch/i386/kernel/smpboot.c | 22 + trunk/arch/i386/kernel/smpcommon.c | 79 --- trunk/arch/i386/kernel/traps.c | 5 + trunk/arch/i386/mach-voyager/voyager_smp.c | 106 ++-- trunk/arch/m68k/lib/uaccess.c | 4 +- trunk/arch/sparc/defconfig | 151 ++--- trunk/arch/sparc/kernel/head.S | 2 +- trunk/arch/sparc64/defconfig | 26 +- trunk/arch/sparc64/kernel/of_device.c | 7 - trunk/arch/sparc64/kernel/smp.c | 3 - trunk/arch/x86_64/kernel/traps.c | 3 + trunk/block/ll_rw_blk.c | 1 + trunk/drivers/block/loop.c | 17 +- trunk/drivers/char/ipmi/ipmi_watchdog.c | 134 +++-- trunk/drivers/infiniband/core/cma.c | 106 ++-- .../drivers/infiniband/hw/ehca/ehca_classes.h | 1 - trunk/drivers/infiniband/hw/ehca/ehca_irq.c | 7 +- trunk/drivers/infiniband/hw/ehca/ehca_main.c | 94 +-- trunk/drivers/infiniband/hw/ehca/ehca_qp.c | 17 +- trunk/drivers/infiniband/hw/ehca/hcp_if.c | 13 +- .../infiniband/hw/ipath/ipath_iba6120.c | 7 +- .../drivers/infiniband/hw/ipath/ipath_intr.c | 7 +- .../infiniband/hw/ipath/ipath_kernel.h | 2 - .../drivers/infiniband/hw/ipath/ipath_verbs.c | 12 +- trunk/drivers/infiniband/hw/mlx4/main.c | 1 - trunk/drivers/infiniband/hw/mthca/mthca_cq.c | 4 +- trunk/drivers/infiniband/hw/mthca/mthca_qp.c | 1 - trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c | 11 +- trunk/drivers/mmc/card/block.c | 17 +- trunk/drivers/mmc/host/au1xmmc.c | 35 +- trunk/drivers/mmc/host/pxamci.c | 18 +- trunk/drivers/mmc/host/sdhci.c | 9 - trunk/drivers/net/Kconfig | 1 - trunk/drivers/net/mlx4/main.c | 2 + trunk/drivers/net/mlx4/mlx4.h | 1 + trunk/drivers/sbus/char/bbc_i2c.c | 1 - trunk/drivers/sbus/char/display7seg.c | 1 - trunk/drivers/scsi/Kconfig | 8 - trunk/drivers/serial/sunhv.c | 4 - trunk/drivers/video/Kconfig | 4 +- trunk/fs/eventpoll.c | 561 ++++++++++-------- trunk/include/asm-alpha/mmu_context.h | 2 +- trunk/include/asm-h8300/atomic.h | 1 - trunk/include/asm-i386/kdebug.h | 1 + trunk/include/asm-i386/processor.h | 4 - trunk/include/asm-m68k/uaccess.h | 4 +- trunk/include/asm-sparc/kdebug.h | 8 +- trunk/include/asm-sparc/system.h | 1 - trunk/include/asm-sparc64/dma-mapping.h | 44 +- trunk/include/asm-x86_64/kdebug.h | 1 + trunk/include/linux/compat.h | 6 - trunk/include/linux/init.h | 7 +- trunk/include/linux/io.h | 8 - trunk/include/linux/major.h | 2 - trunk/include/linux/slub_def.h | 6 +- trunk/kernel/time/clocksource.c | 10 +- trunk/kernel/time/timekeeping.c | 2 - trunk/kernel/timer.c | 2 + trunk/net/ipv4/proc.c | 21 - trunk/net/ipv6/ip6_input.c | 2 +- trunk/net/sched/sch_prio.c | 2 +- trunk/net/xfrm/xfrm_hash.c | 3 +- trunk/net/xfrm/xfrm_policy.c | 4 - 69 files changed, 891 insertions(+), 832 deletions(-) delete mode 100644 trunk/arch/i386/kernel/smpcommon.c diff --git a/[refs] b/[refs] index 26d76390a1ae..235db34a70e3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f653c34dd3d8bde2c918316fd5ba2e2c4f95afcf +refs/heads/master: 30046e5885848fe5c2c66177dca6b277323e31ab diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index bbeb5b6b5b05..68a56add73e3 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1712,6 +1712,8 @@ L: Linux-Kernel@vger.kernel.org S: Maintained i386 SETUP CODE / CPU ERRATA WORKAROUNDS +P: Dave Jones +M: davej@codemonkey.org.uk P: H. Peter Anvin M: hpa@zytor.com S: Maintained @@ -3267,7 +3269,6 @@ W: http://tpmdd.sourceforge.net P: Marcel Selhorst M: tpm@selhorst.net W: http://www.prosec.rub.de/tpm/ -L: tpmdd-devel@lists.sourceforge.net S: Maintained Telecom Clock Driver for MCPL0010 diff --git a/trunk/arch/i386/kernel/Makefile b/trunk/arch/i386/kernel/Makefile index 06da59f6f837..91cff8dc9e1a 100644 --- a/trunk/arch/i386/kernel/Makefile +++ b/trunk/arch/i386/kernel/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o tsc_sync.o -obj-$(CONFIG_SMP) += smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 7cf3d207b6b3..5c715f17a679 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -521,7 +521,7 @@ static int check_supported_cpu(unsigned int cpu) if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_H)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 95be5013c984..ae2d9da084dd 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -46,8 +46,8 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_G 0x00060000 -#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ +#define CPUID_XMOD_REV_H 0x00070000 +#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 diff --git a/trunk/arch/i386/kernel/smp.c b/trunk/arch/i386/kernel/smp.c index c9a7c9835aba..706bda72dc60 100644 --- a/trunk/arch/i386/kernel/smp.c +++ b/trunk/arch/i386/kernel/smp.c @@ -467,7 +467,7 @@ void flush_tlb_all(void) * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ -static void native_smp_send_reschedule(int cpu) +void native_smp_send_reschedule(int cpu) { WARN_ON(cpu_is_offline(cpu)); send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); @@ -546,10 +546,9 @@ static void __smp_call_function(void (*func) (void *info), void *info, * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -static int -native_smp_call_function_mask(cpumask_t mask, - void (*func)(void *), void *info, - int wait) +int native_smp_call_function_mask(cpumask_t mask, + void (*func)(void *), void *info, + int wait) { struct call_data_struct data; cpumask_t allbutself; @@ -600,6 +599,60 @@ native_smp_call_function_mask(cpumask_t mask, return 0; } +/** + * smp_call_function(): Run a function on all other CPUs. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait (atomically) until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + * + * 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(void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + return smp_call_function_mask(cpu_online_map, func, info, wait); +} +EXPORT_SYMBOL(smp_call_function); + +/** + * smp_call_function_single - Run a function on another CPU + * @cpu: The target CPU. Cannot be the calling CPU. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + */ +int smp_call_function_single(int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + /* prevent preemption and reschedule on another processor */ + int ret; + int me = get_cpu(); + if (cpu == me) { + WARN_ON(1); + put_cpu(); + return -EBUSY; + } + + ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); + + put_cpu(); + return ret; +} +EXPORT_SYMBOL(smp_call_function_single); + static void stop_this_cpu (void * dummy) { local_irq_disable(); @@ -617,7 +670,7 @@ static void stop_this_cpu (void * dummy) * this function calls the 'stop' function on all other CPUs in the system. */ -static void native_smp_send_stop(void) +void native_smp_send_stop(void) { /* Don't deadlock on the call lock in panic */ int nolock = !spin_trylock(&call_lock); diff --git a/trunk/arch/i386/kernel/smpboot.c b/trunk/arch/i386/kernel/smpboot.c index 08f07a74a9d3..b92cc4e8b3bb 100644 --- a/trunk/arch/i386/kernel/smpboot.c +++ b/trunk/arch/i386/kernel/smpboot.c @@ -98,6 +98,9 @@ EXPORT_SYMBOL(x86_cpu_to_apicid); u8 apicid_2_node[MAX_APICID]; +DEFINE_PER_CPU(unsigned long, this_cpu_off); +EXPORT_PER_CPU_SYMBOL(this_cpu_off); + /* * Trampoline 80x86 program as an array. */ @@ -760,6 +763,25 @@ static inline struct task_struct * alloc_idle_task(int cpu) #define alloc_idle_task(cpu) fork_idle(cpu) #endif +/* Initialize the CPU's GDT. This is either the boot CPU doing itself + (still using the master per-cpu area), or a CPU doing it for a + secondary which will soon come up. */ +static __cpuinit void init_gdt(int cpu) +{ + struct desc_struct *gdt = get_cpu_gdt_table(cpu); + + pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], 0xFFFFF, + 0x80 | DESCTYPE_S | 0x2, 0x8); + + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; + per_cpu(cpu_number, cpu) = cpu; +} + +/* Defined in head.S */ +extern struct Xgt_desc_struct early_gdt_descr; + static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad diff --git a/trunk/arch/i386/kernel/smpcommon.c b/trunk/arch/i386/kernel/smpcommon.c deleted file mode 100644 index 1868ae18eb4d..000000000000 --- a/trunk/arch/i386/kernel/smpcommon.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SMP stuff which is common to all sub-architectures. - */ -#include -#include - -DEFINE_PER_CPU(unsigned long, this_cpu_off); -EXPORT_PER_CPU_SYMBOL(this_cpu_off); - -/* Initialize the CPU's GDT. This is either the boot CPU doing itself - (still using the master per-cpu area), or a CPU doing it for a - secondary which will soon come up. */ -__cpuinit void init_gdt(int cpu) -{ - struct desc_struct *gdt = get_cpu_gdt_table(cpu); - - pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, - (u32 *)&gdt[GDT_ENTRY_PERCPU].b, - __per_cpu_offset[cpu], 0xFFFFF, - 0x80 | DESCTYPE_S | 0x2, 0x8); - - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; - per_cpu(cpu_number, cpu) = cpu; -} - - -/** - * smp_call_function(): Run a function on all other CPUs. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait (atomically) until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - * - * 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(void (*func) (void *info), void *info, int nonatomic, - int wait) -{ - return smp_call_function_mask(cpu_online_map, func, info, wait); -} -EXPORT_SYMBOL(smp_call_function); - -/** - * smp_call_function_single - Run a function on another CPU - * @cpu: The target CPU. Cannot be the calling CPU. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - */ -int smp_call_function_single(int cpu, void (*func) (void *info), void *info, - int nonatomic, int wait) -{ - /* prevent preemption and reschedule on another processor */ - int ret; - int me = get_cpu(); - if (cpu == me) { - WARN_ON(1); - put_cpu(); - return -EBUSY; - } - - ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); - - put_cpu(); - return ret; -} -EXPORT_SYMBOL(smp_call_function_single); diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index 90da0575fcff..c05e7e861b29 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -733,6 +733,11 @@ static __kprobes void default_do_nmi(struct pt_regs * regs) */ if (nmi_watchdog_tick(regs, reason)) return; +#endif + if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0) + == NOTIFY_STOP) + return; +#ifdef CONFIG_X86_LOCAL_APIC if (!do_nmi_callback(regs, smp_processor_id())) #endif unknown_nmi_error(reason, regs); diff --git a/trunk/arch/i386/mach-voyager/voyager_smp.c b/trunk/arch/i386/mach-voyager/voyager_smp.c index b87f8548e75a..50d9c52070b1 100644 --- a/trunk/arch/i386/mach-voyager/voyager_smp.c +++ b/trunk/arch/i386/mach-voyager/voyager_smp.c @@ -27,6 +27,7 @@ #include #include #include +#include /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; @@ -421,7 +422,7 @@ find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; - x86_write_percpu(cpu_number, boot_cpu_id); + write_pda(cpu_number, boot_cpu_id); } /* @@ -434,7 +435,7 @@ smp_store_cpu_info(int id) *c = boot_cpu_data; - identify_secondary_cpu(c); + identify_cpu(c); } /* set up the trampoline and return the physical address of the code */ @@ -458,7 +459,7 @@ start_secondary(void *unused) /* external functions not defined in the headers */ extern void calibrate_delay(void); - cpu_init(); + secondary_cpu_init(); /* OK, we're in the routine */ ack_CPI(VIC_CPU_BOOT_CPI); @@ -571,9 +572,7 @@ do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; - init_gdt(cpu); - per_cpu(current_task, cpu) = idle; - early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); + init_gdt(cpu, idle); irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -860,8 +859,8 @@ smp_invalidate_interrupt(void) /* This routine is called with a physical cpu mask */ static void -voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, - unsigned long va) +flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, + unsigned long va) { int stuck = 50000; @@ -913,7 +912,7 @@ flush_tlb_current_task(void) cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id()); local_flush_tlb(); if (cpu_mask) - voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -935,7 +934,7 @@ flush_tlb_mm (struct mm_struct * mm) leave_mm(smp_processor_id()); } if (cpu_mask) - voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -956,7 +955,7 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) } if (cpu_mask) - voyager_flush_tlb_others(cpu_mask, mm, va); + flush_tlb_others(cpu_mask, mm, va); preempt_enable(); } @@ -1045,12 +1044,10 @@ smp_call_function_interrupt(void) } static int -voyager_smp_call_function_mask (cpumask_t cpumask, - void (*func) (void *info), void *info, - int wait) +__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(cpumask)[0]; mask &= ~(1< 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. +*/ +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 + * 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, @@ -1199,8 +1237,8 @@ smp_alloc_memory(void) } /* send a reschedule CPI to one CPU by physical CPU number*/ -static void -voyager_smp_send_reschedule(int cpu) +void +smp_send_reschedule(int cpu) { send_one_CPI(cpu, VIC_RESCHEDULE_CPI); } @@ -1229,8 +1267,8 @@ safe_smp_processor_id(void) } /* broadcast a halt to all other CPUs */ -static void -voyager_smp_send_stop(void) +void +smp_send_stop(void) { smp_call_function(smp_stop_cpu_function, NULL, 1, 1); } @@ -1892,26 +1930,23 @@ smp_voyager_power_off(void *dummy) smp_stop_cpu_function(NULL); } -static void __init -voyager_smp_prepare_cpus(unsigned int max_cpus) +void __init +smp_prepare_cpus(unsigned int max_cpus) { /* FIXME: ignore max_cpus for now */ smp_boot_cpus(); } -static void __devinit voyager_smp_prepare_boot_cpu(void) +void __devinit smp_prepare_boot_cpu(void) { - init_gdt(smp_processor_id()); - switch_to_new_gdt(); - cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_callout_map); cpu_set(smp_processor_id(), cpu_possible_map); cpu_set(smp_processor_id(), cpu_present_map); } -static int __devinit -voyager_cpu_up(unsigned int cpu) +int __devinit +__cpu_up(unsigned int cpu) { /* This only works at boot for x86. See "rewrite" above. */ if (cpu_isset(cpu, smp_commenced_mask)) @@ -1927,8 +1962,8 @@ voyager_cpu_up(unsigned int cpu) return 0; } -static void __init -voyager_smp_cpus_done(unsigned int max_cpus) +void __init +smp_cpus_done(unsigned int max_cpus) { zap_low_mappings(); } @@ -1937,16 +1972,5 @@ void __init smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); - x86_write_percpu(cpu_number, hard_smp_processor_id()); + write_pda(cpu_number, hard_smp_processor_id()); } - -struct smp_ops smp_ops = { - .smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu, - .smp_prepare_cpus = voyager_smp_prepare_cpus, - .cpu_up = voyager_cpu_up, - .smp_cpus_done = voyager_smp_cpus_done, - - .smp_send_stop = voyager_smp_send_stop, - .smp_send_reschedule = voyager_smp_send_reschedule, - .smp_call_function_mask = voyager_smp_call_function_mask, -}; diff --git a/trunk/arch/m68k/lib/uaccess.c b/trunk/arch/m68k/lib/uaccess.c index 13854ed8cd9a..865f9fb9e686 100644 --- a/trunk/arch/m68k/lib/uaccess.c +++ b/trunk/arch/m68k/lib/uaccess.c @@ -181,7 +181,7 @@ EXPORT_SYMBOL(strnlen_user); * Zero Userspace */ -unsigned long __clear_user(void __user *to, unsigned long n) +unsigned long clear_user(void __user *to, unsigned long n) { unsigned long res; @@ -219,4 +219,4 @@ unsigned long __clear_user(void __user *to, unsigned long n) return res; } -EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(clear_user); diff --git a/trunk/arch/sparc/defconfig b/trunk/arch/sparc/defconfig index 38bd79fe6e75..79e54894529d 100644 --- a/trunk/arch/sparc/defconfig +++ b/trunk/arch/sparc/defconfig @@ -1,11 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22-rc1 -# Mon May 14 03:25:14 2007 +# Linux kernel version: 2.6.20-rc1 +# Sun Dec 17 14:20:47 2006 # CONFIG_MMU=y CONFIG_HIGHMEM=y -CONFIG_ZONE_DMA=y CONFIG_GENERIC_ISA_DMA=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -24,17 +23,14 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_IPC_NS is not set -CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y @@ -50,19 +46,14 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set +CONFIG_VM_EVENT_COUNTERS=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -116,7 +107,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_SUN_PM=y # CONFIG_SUN4 is not set CONFIG_PCI=y -# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_MULTITHREAD_PROBE is not set # CONFIG_PCI_DEBUG is not set CONFIG_SUN_OPENPROMFS=m # CONFIG_SPARC_LED is not set @@ -133,7 +124,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 # # Networking @@ -143,15 +133,14 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=m -# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -181,7 +170,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y # CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m @@ -241,18 +229,7 @@ CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -CONFIG_AF_RXRPC=m -# CONFIG_AF_RXRPC_DEBUG is not set -# CONFIG_RXKAD is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set # # Device Drivers @@ -265,13 +242,16 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker # # CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# # CONFIG_MTD is not set # @@ -282,7 +262,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # -# CONFIG_PNPACPI is not set # # Block devices @@ -301,16 +280,15 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # # Misc devices # -# CONFIG_PHANTOM is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set -# CONFIG_BLINK is not set # # ATA/ATAPI/MFM/RLL support @@ -344,12 +322,11 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports # -CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SPI_ATTRS=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set @@ -389,9 +366,12 @@ CONFIG_SCSI_QLOGICPTI=m # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set -CONFIG_SCSI_ESP_CORE=y CONFIG_SCSI_SUNESP=y # CONFIG_SCSI_SRP is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# # CONFIG_ATA is not set # @@ -410,7 +390,6 @@ CONFIG_SCSI_SUNESP=y # # IEEE 1394 (FireWire) support # -# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # @@ -431,6 +410,10 @@ CONFIG_TUN=m # ARCnet devices # # CONFIG_ARCNET is not set + +# +# PHY device support +# # CONFIG_PHYLIB is not set # @@ -452,7 +435,10 @@ CONFIG_SUNQE=m # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_NET_PCI is not set -CONFIG_NETDEV_1000=y + +# +# Ethernet (1000 Mbit) +# # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set @@ -468,16 +454,15 @@ CONFIG_NETDEV_1000=y # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set -# CONFIG_ATL1 is not set -CONFIG_NETDEV_10000=y + +# +# Ethernet (10000 Mbit) +# # CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set -# CONFIG_MLX4_CORE is not set -CONFIG_MLX4_DEBUG=y # # Token Ring devices @@ -485,10 +470,13 @@ CONFIG_MLX4_DEBUG=y # CONFIG_TR is not set # -# Wireless LAN +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces # -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -540,17 +528,9 @@ CONFIG_KEYBOARD_SUNKBD=m # CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=m -# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -598,9 +578,14 @@ CONFIG_LEGACY_PTY_COUNT=256 # IPMI # # CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=m CONFIG_RTC=m +# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_DRM is not set @@ -610,7 +595,10 @@ CONFIG_RTC=m # TPM devices # # CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y + +# +# I2C support +# # CONFIG_I2C is not set # @@ -623,39 +611,32 @@ CONFIG_DEVPORT=y # Dallas's 1-wire bus # # CONFIG_W1 is not set + +# +# Hardware Monitoring support +# CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83627HF is not set # CONFIG_HWMON_DEBUG_CHIP is not set -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - # # Multimedia devices # # CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set # -# Graphics support +# Digital Video Broadcasting Devices # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DVB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set +CONFIG_FIRMWARE_EDID=y # CONFIG_FB is not set # @@ -663,6 +644,7 @@ CONFIG_HWMON=y # # CONFIG_PROM_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -673,7 +655,6 @@ CONFIG_DUMMY_CONSOLE=y # HID Devices # CONFIG_HID=y -# CONFIG_HID_DEBUG is not set # # USB support @@ -691,6 +672,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y # USB Gadget Support # # CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# # CONFIG_MMC is not set # @@ -733,6 +718,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y # DMA Devices # +# +# Virtualization +# + # # Misc Linux/SPARC drivers # @@ -812,7 +801,6 @@ CONFIG_RAMFS=y # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set CONFIG_BEFS_FS=m @@ -839,7 +827,6 @@ CONFIG_LOCKD=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=m -# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -852,7 +839,7 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set CONFIG_AFS_FS=m -# CONFIG_AFS_DEBUG is not set +CONFIG_RXRPC=m # CONFIG_9P_FS is not set # @@ -926,14 +913,15 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set @@ -944,14 +932,12 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACK_USAGE is not set # # Security options # -CONFIG_KEYS=y -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -975,11 +961,8 @@ CONFIG_CRYPTO_SHA512=m # CONFIG_CRYPTO_GF128MUL is not set CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_TWOFISH_COMMON=m @@ -994,7 +977,6 @@ CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set # @@ -1007,12 +989,9 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y +CONFIG_IOMAP_COPY=y diff --git a/trunk/arch/sparc/kernel/head.S b/trunk/arch/sparc/kernel/head.S index 9a219e8b5ddb..97da13c52563 100644 --- a/trunk/arch/sparc/kernel/head.S +++ b/trunk/arch/sparc/kernel/head.S @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include /* TI_UWINMASK */ #include diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index 65840a62bb9c..585ef4fb7591 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22-rc1 -# Mon May 14 04:17:48 2007 +# Linux kernel version: 2.6.21 +# Fri May 11 14:31:45 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -508,6 +508,10 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_ESP_CORE is not set # CONFIG_SCSI_SUNESP is not set # CONFIG_SCSI_SRP is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# # CONFIG_ATA is not set # @@ -564,6 +568,10 @@ CONFIG_DUMMY=m # ARCnet devices # # CONFIG_ARCNET is not set + +# +# PHY device support +# # CONFIG_PHYLIB is not set # @@ -603,7 +611,10 @@ CONFIG_NET_PCI=y # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set -CONFIG_NETDEV_1000=y + +# +# Ethernet (1000 Mbit) +# # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=m @@ -623,7 +634,10 @@ CONFIG_TIGON3=m CONFIG_BNX2=m # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set -CONFIG_NETDEV_10000=y + +# +# Ethernet (10000 Mbit) +# # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set @@ -653,6 +667,10 @@ CONFIG_MLX4_DEBUG=y # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set + +# +# Wan interfaces +# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set diff --git a/trunk/arch/sparc64/kernel/of_device.c b/trunk/arch/sparc64/kernel/of_device.c index 16cc46a71872..7455f5d05519 100644 --- a/trunk/arch/sparc64/kernel/of_device.c +++ b/trunk/arch/sparc64/kernel/of_device.c @@ -537,13 +537,6 @@ static int __init build_one_resource(struct device_node *parent, return 0; } - /* When we miss an I/O space match on PCI, just pass it up - * to the next PCI bridge and/or controller. - */ - if (!strcmp(bus->name, "pci") && - (addr[0] & 0x03000000) == 0x01000000) - return 0; - return 1; } diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index 24fdf1d0adc5..8087d67a0cf8 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -561,9 +561,6 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t unsigned long flags, status; int cnt, retries, this_cpu, prev_sent, i; - if (cpus_empty(mask)) - return; - /* We have to do this whole thing with interrupts fully disabled. * Otherwise if we send an xcall from interrupt context it will * corrupt both our mondo block and cpu list state. diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index cb29fb96948d..d28f01379b9b 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -776,6 +776,9 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs) */ if (nmi_watchdog_tick(regs,reason)) return; + if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0) + == NOTIFY_STOP) + return; if (!do_nmi_callback(regs,cpu)) unknown_nmi_error(reason, regs); diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 6b5173ac8131..74a567afb830 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -3802,6 +3802,7 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node) return ret; } +EXPORT_SYMBOL(current_io_context); /* * If the current task has no IO context then create one and initialise it. diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 5526eadb6592..e2fc4b6734cf 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -1399,11 +1399,6 @@ static struct loop_device *loop_init_one(int i) struct loop_device *lo; struct gendisk *disk; - list_for_each_entry(lo, &loop_devices, lo_list) { - if (lo->lo_number == i) - return lo; - } - lo = kzalloc(sizeof(*lo), GFP_KERNEL); if (!lo) goto out; @@ -1448,13 +1443,17 @@ static void loop_del_one(struct loop_device *lo) kfree(lo); } +static int loop_lock(dev_t dev, void *data) +{ + mutex_lock(&loop_devices_mutex); + return 0; +} + static struct kobject *loop_probe(dev_t dev, int *part, void *data) { - struct loop_device *lo; + struct loop_device *lo = loop_init_one(dev & MINORMASK); struct kobject *kobj; - mutex_lock(&loop_devices_mutex); - lo = loop_init_one(dev & MINORMASK); kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); mutex_unlock(&loop_devices_mutex); @@ -1467,7 +1466,7 @@ static int __init loop_init(void) if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, - THIS_MODULE, loop_probe, NULL, NULL); + THIS_MODULE, loop_probe, loop_lock, NULL); if (max_loop) { printk(KERN_INFO "loop: the max_loop option is obsolete " diff --git a/trunk/drivers/char/ipmi/ipmi_watchdog.c b/trunk/drivers/char/ipmi/ipmi_watchdog.c index 41f78e2c158f..147c12047cf3 100644 --- a/trunk/drivers/char/ipmi/ipmi_watchdog.c +++ b/trunk/drivers/char/ipmi/ipmi_watchdog.c @@ -50,10 +50,18 @@ #include #include #include +#include #include -#ifdef CONFIG_X86_LOCAL_APIC -#include +#ifdef CONFIG_X86 +/* This is ugly, but I've determined that x86 is the only architecture + that can reasonably support the IPMI NMI watchdog timeout at this + time. If another architecture adds this capability somehow, it + will have to be a somewhat different mechanism and I have no idea + how it will work. So in the unlikely event that another + architecture supports this, we can figure out a good generic + mechanism for it at that time. */ +#define HAVE_DIE_NMI_POST #endif #define PFX "IPMI Watchdog: " @@ -319,6 +327,11 @@ static unsigned char ipmi_version_minor; /* If a pretimeout occurs, this is used to allow only one panic to happen. */ static atomic_t preop_panic_excl = ATOMIC_INIT(-1); +#ifdef HAVE_DIE_NMI_POST +static int testing_nmi; +static int nmi_handler_registered; +#endif + static int ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void); @@ -360,6 +373,10 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, int hbnow = 0; + /* These can be cleared as we are setting the timeout. */ + ipmi_start_timer_on_heartbeat = 0; + pretimeout_since_last_heartbeat = 0; + data[0] = 0; WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); @@ -434,13 +451,12 @@ static int ipmi_set_timeout(int do_heartbeat) wait_for_completion(&set_timeout_wait); + mutex_unlock(&set_timeout_lock); + if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) || ((send_heartbeat_now) && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) - { rv = ipmi_heartbeat(); - } - mutex_unlock(&set_timeout_lock); out: return rv; @@ -520,12 +536,10 @@ static int ipmi_heartbeat(void) int rv; struct ipmi_system_interface_addr addr; - if (ipmi_ignore_heartbeat) { + if (ipmi_ignore_heartbeat) return 0; - } if (ipmi_start_timer_on_heartbeat) { - ipmi_start_timer_on_heartbeat = 0; ipmi_watchdog_state = action_val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } else if (pretimeout_since_last_heartbeat) { @@ -533,7 +547,6 @@ static int ipmi_heartbeat(void) We don't want to set the action, though, we want to leave that alone (thus it can't be combined with the above operation. */ - pretimeout_since_last_heartbeat = 0; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } @@ -921,6 +934,45 @@ static void ipmi_register_watchdog(int ipmi_intf) printk(KERN_CRIT PFX "Unable to register misc device\n"); } +#ifdef HAVE_DIE_NMI_POST + if (nmi_handler_registered) { + int old_pretimeout = pretimeout; + int old_timeout = timeout; + int old_preop_val = preop_val; + + /* Set the pretimeout to go off in a second and give + ourselves plenty of time to stop the timer. */ + ipmi_watchdog_state = WDOG_TIMEOUT_RESET; + preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */ + pretimeout = 99; + timeout = 100; + + testing_nmi = 1; + + rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); + if (rv) { + printk(KERN_WARNING PFX "Error starting timer to" + " test NMI: 0x%x. The NMI pretimeout will" + " likely not work\n", rv); + rv = 0; + goto out_restore; + } + + msleep(1500); + + if (testing_nmi != 2) { + printk(KERN_WARNING PFX "IPMI NMI didn't seem to" + " occur. The NMI pretimeout will" + " likely not work\n"); + } + out_restore: + testing_nmi = 0; + preop_val = old_preop_val; + pretimeout = old_pretimeout; + timeout = old_timeout; + } +#endif + out: up_write(®ister_sem); @@ -930,6 +982,10 @@ static void ipmi_register_watchdog(int ipmi_intf) ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); printk(KERN_INFO PFX "Starting now!\n"); + } else { + /* Stop the timer now. */ + ipmi_watchdog_state = WDOG_TIMEOUT_NONE; + ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } } @@ -966,17 +1022,28 @@ static void ipmi_unregister_watchdog(int ipmi_intf) up_write(®ister_sem); } -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST static int -ipmi_nmi(void *dev_id, int cpu, int handled) +ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) { + if (val != DIE_NMI_POST) + return NOTIFY_OK; + + if (testing_nmi) { + testing_nmi = 2; + return NOTIFY_STOP; + } + /* If we are not expecting a timeout, ignore it. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) - return NOTIFY_DONE; + return NOTIFY_OK; + + if (preaction_val != WDOG_PRETIMEOUT_NMI) + return NOTIFY_OK; /* If no one else handled the NMI, we assume it was the IPMI watchdog. */ - if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { + if (preop_val == WDOG_PREOP_PANIC) { /* On some machines, the heartbeat will give an error and not work unless we re-enable the timer. So do so. */ @@ -985,18 +1052,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled) panic(PFX "pre-timeout"); } - return NOTIFY_DONE; + return NOTIFY_STOP; } -static struct nmi_handler ipmi_nmi_handler = -{ - .link = LIST_HEAD_INIT(ipmi_nmi_handler.link), - .dev_name = "ipmi_watchdog", - .dev_id = NULL, - .handler = ipmi_nmi, - .priority = 0, /* Call us last. */ +static struct notifier_block ipmi_nmi_handler = { + .notifier_call = ipmi_nmi }; -int nmi_handler_registered; #endif static int wdog_reboot_handler(struct notifier_block *this, @@ -1113,7 +1174,7 @@ static int preaction_op(const char *inval, char *outval) preaction_val = WDOG_PRETIMEOUT_NONE; else if (strcmp(inval, "pre_smi") == 0) preaction_val = WDOG_PRETIMEOUT_SMI; -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST else if (strcmp(inval, "pre_nmi") == 0) preaction_val = WDOG_PRETIMEOUT_NMI; #endif @@ -1147,7 +1208,7 @@ static int preop_op(const char *inval, char *outval) static void check_parms(void) { -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST int do_nmi = 0; int rv; @@ -1160,20 +1221,9 @@ static void check_parms(void) preop_op("preop_none", NULL); do_nmi = 0; } -#ifdef CONFIG_X86_LOCAL_APIC - if (nmi_watchdog == NMI_IO_APIC) { - printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC" - " mode (value is %d), that is incompatible" - " with using NMI in the IPMI watchdog." - " Disabling IPMI nmi pretimeout.\n", - nmi_watchdog); - preaction_val = WDOG_PRETIMEOUT_NONE; - do_nmi = 0; - } -#endif } if (do_nmi && !nmi_handler_registered) { - rv = request_nmi(&ipmi_nmi_handler); + rv = register_die_notifier(&ipmi_nmi_handler); if (rv) { printk(KERN_WARNING PFX "Can't register nmi handler\n"); @@ -1181,7 +1231,7 @@ static void check_parms(void) } else nmi_handler_registered = 1; } else if (!do_nmi && nmi_handler_registered) { - release_nmi(&ipmi_nmi_handler); + unregister_die_notifier(&ipmi_nmi_handler); nmi_handler_registered = 0; } #endif @@ -1217,9 +1267,9 @@ static int __init ipmi_wdog_init(void) rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { -#ifdef HAVE_NMI_HANDLER - if (preaction_val == WDOG_PRETIMEOUT_NMI) - release_nmi(&ipmi_nmi_handler); +#ifdef HAVE_DIE_NMI_POST + if (nmi_handler_registered) + unregister_die_notifier(&ipmi_nmi_handler); #endif atomic_notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); @@ -1238,9 +1288,9 @@ static void __exit ipmi_wdog_exit(void) ipmi_smi_watcher_unregister(&smi_watcher); ipmi_unregister_watchdog(watchdog_ifnum); -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST if (nmi_handler_registered) - release_nmi(&ipmi_nmi_handler); + unregister_die_notifier(&ipmi_nmi_handler); #endif atomic_notifier_chain_unregister(&panic_notifier_list, diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c index 2eb52b7a71da..fde92ce45153 100644 --- a/trunk/drivers/infiniband/core/cma.c +++ b/trunk/drivers/infiniband/core/cma.c @@ -346,33 +346,12 @@ static void cma_deref_id(struct rdma_id_private *id_priv) complete(&id_priv->comp); } -static int cma_disable_remove(struct rdma_id_private *id_priv, - enum cma_state state) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&id_priv->lock, flags); - if (id_priv->state == state) { - atomic_inc(&id_priv->dev_remove); - ret = 0; - } else - ret = -EINVAL; - spin_unlock_irqrestore(&id_priv->lock, flags); - return ret; -} - -static void cma_enable_remove(struct rdma_id_private *id_priv) +static void cma_release_remove(struct rdma_id_private *id_priv) { if (atomic_dec_and_test(&id_priv->dev_remove)) wake_up(&id_priv->wait_remove); } -static int cma_has_cm_dev(struct rdma_id_private *id_priv) -{ - return (id_priv->id.device && id_priv->cm_id.ib); -} - struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, void *context, enum rdma_port_space ps) { @@ -905,8 +884,9 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) struct rdma_cm_event event; int ret = 0; - if (cma_disable_remove(id_priv, CMA_CONNECT)) - return 0; + atomic_inc(&id_priv->dev_remove); + if (!cma_comp(id_priv, CMA_CONNECT)) + goto out; memset(&event, 0, sizeof event); switch (ib_event->event) { @@ -962,12 +942,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; cma_exch(id_priv, CMA_DESTROYING); - cma_enable_remove(id_priv); + cma_release_remove(id_priv); rdma_destroy_id(&id_priv->id); return ret; } out: - cma_enable_remove(id_priv); + cma_release_remove(id_priv); return ret; } @@ -1077,8 +1057,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) int offset, ret; listen_id = cm_id->context; - if (cma_disable_remove(listen_id, CMA_LISTEN)) - return -ECONNABORTED; + atomic_inc(&listen_id->dev_remove); + if (!cma_comp(listen_id, CMA_LISTEN)) { + ret = -ECONNABORTED; + goto out; + } memset(&event, 0, sizeof event); offset = cma_user_data_offset(listen_id->id.ps); @@ -1118,11 +1101,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) release_conn_id: cma_exch(conn_id, CMA_DESTROYING); - cma_enable_remove(conn_id); + cma_release_remove(conn_id); rdma_destroy_id(&conn_id->id); out: - cma_enable_remove(listen_id); + cma_release_remove(listen_id); return ret; } @@ -1188,10 +1171,9 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) struct sockaddr_in *sin; int ret = 0; - if (cma_disable_remove(id_priv, CMA_CONNECT)) - return 0; - memset(&event, 0, sizeof event); + atomic_inc(&id_priv->dev_remove); + switch (iw_event->event) { case IW_CM_EVENT_CLOSE: event.event = RDMA_CM_EVENT_DISCONNECTED; @@ -1232,12 +1214,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.iw = NULL; cma_exch(id_priv, CMA_DESTROYING); - cma_enable_remove(id_priv); + cma_release_remove(id_priv); rdma_destroy_id(&id_priv->id); return ret; } - cma_enable_remove(id_priv); + cma_release_remove(id_priv); return ret; } @@ -1252,8 +1234,11 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, int ret; listen_id = cm_id->context; - if (cma_disable_remove(listen_id, CMA_LISTEN)) - return -ECONNABORTED; + atomic_inc(&listen_id->dev_remove); + if (!cma_comp(listen_id, CMA_LISTEN)) { + ret = -ECONNABORTED; + goto out; + } /* Create a new RDMA id for the new IW CM ID */ new_cm_id = rdma_create_id(listen_id->id.event_handler, @@ -1270,13 +1255,13 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr); if (!dev) { ret = -EADDRNOTAVAIL; - cma_enable_remove(conn_id); + cma_release_remove(conn_id); rdma_destroy_id(new_cm_id); goto out; } ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL); if (ret) { - cma_enable_remove(conn_id); + cma_release_remove(conn_id); rdma_destroy_id(new_cm_id); goto out; } @@ -1285,7 +1270,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, ret = cma_acquire_dev(conn_id); mutex_unlock(&lock); if (ret) { - cma_enable_remove(conn_id); + cma_release_remove(conn_id); rdma_destroy_id(new_cm_id); goto out; } @@ -1308,14 +1293,14 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, /* User wants to destroy the CM ID */ conn_id->cm_id.iw = NULL; cma_exch(conn_id, CMA_DESTROYING); - cma_enable_remove(conn_id); + cma_release_remove(conn_id); rdma_destroy_id(&conn_id->id); } out: if (dev) dev_put(dev); - cma_enable_remove(listen_id); + cma_release_remove(listen_id); return ret; } @@ -1534,7 +1519,7 @@ static void cma_work_handler(struct work_struct *_work) destroy = 1; } out: - cma_enable_remove(id_priv); + cma_release_remove(id_priv); cma_deref_id(id_priv); if (destroy) rdma_destroy_id(&id_priv->id); @@ -1726,13 +1711,13 @@ static void addr_handler(int status, struct sockaddr *src_addr, if (id_priv->id.event_handler(&id_priv->id, &event)) { cma_exch(id_priv, CMA_DESTROYING); - cma_enable_remove(id_priv); + cma_release_remove(id_priv); cma_deref_id(id_priv); rdma_destroy_id(&id_priv->id); return; } out: - cma_enable_remove(id_priv); + cma_release_remove(id_priv); cma_deref_id(id_priv); } @@ -2057,10 +2042,11 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; int ret = 0; - if (cma_disable_remove(id_priv, CMA_CONNECT)) - return 0; - memset(&event, 0, sizeof event); + atomic_inc(&id_priv->dev_remove); + if (!cma_comp(id_priv, CMA_CONNECT)) + goto out; + switch (ib_event->event) { case IB_CM_SIDR_REQ_ERROR: event.event = RDMA_CM_EVENT_UNREACHABLE; @@ -2098,12 +2084,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; cma_exch(id_priv, CMA_DESTROYING); - cma_enable_remove(id_priv); + cma_release_remove(id_priv); rdma_destroy_id(&id_priv->id); return ret; } out: - cma_enable_remove(id_priv); + cma_release_remove(id_priv); return ret; } @@ -2427,7 +2413,7 @@ int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event) int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_has_cm_dev(id_priv)) + if (!cma_comp(id_priv, CMA_CONNECT)) return -EINVAL; switch (id->device->node_type) { @@ -2449,7 +2435,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_has_cm_dev(id_priv)) + if (!cma_comp(id_priv, CMA_CONNECT)) return -EINVAL; switch (rdma_node_get_transport(id->device->node_type)) { @@ -2480,7 +2466,8 @@ int rdma_disconnect(struct rdma_cm_id *id) int ret; id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_has_cm_dev(id_priv)) + if (!cma_comp(id_priv, CMA_CONNECT) && + !cma_comp(id_priv, CMA_DISCONNECT)) return -EINVAL; switch (rdma_node_get_transport(id->device->node_type)) { @@ -2512,9 +2499,10 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) int ret; id_priv = mc->id_priv; - if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) && - cma_disable_remove(id_priv, CMA_ADDR_RESOLVED)) - return 0; + atomic_inc(&id_priv->dev_remove); + if (!cma_comp(id_priv, CMA_ADDR_BOUND) && + !cma_comp(id_priv, CMA_ADDR_RESOLVED)) + goto out; if (!status && id_priv->id.qp) status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid, @@ -2536,12 +2524,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) ret = id_priv->id.event_handler(&id_priv->id, &event); if (ret) { cma_exch(id_priv, CMA_DESTROYING); - cma_enable_remove(id_priv); + cma_release_remove(id_priv); rdma_destroy_id(&id_priv->id); return 0; } - - cma_enable_remove(id_priv); +out: + cma_release_remove(id_priv); return 0; } diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index 1d286d3cc2d5..f64d42b08674 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -277,7 +277,6 @@ void ehca_cleanup_mrmw_cache(void); extern spinlock_t ehca_qp_idr_lock; extern spinlock_t ehca_cq_idr_lock; -extern spinlock_t hcall_lock; extern struct idr ehca_qp_idr; extern struct idr ehca_cq_idr; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c index 100329ba3343..82dda2faf4d0 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c @@ -517,11 +517,12 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) else { struct ehca_cq *cq = eq->eqe_cache[i].cq; comp_event_callback(cq); - spin_lock(&ehca_cq_idr_lock); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); cq->nr_events--; if (!cq->nr_events) wake_up(&cq->wait_completion); - spin_unlock(&ehca_cq_idr_lock); + spin_unlock_irqrestore(&ehca_cq_idr_lock, + flags); } } else { ehca_dbg(&shca->ib_device, "Got non completion event"); @@ -710,7 +711,6 @@ static void destroy_comp_task(struct ehca_comp_pool *pool, kthread_stop(task); } -#ifdef CONFIG_HOTPLUG_CPU static void take_over_work(struct ehca_comp_pool *pool, int cpu) { @@ -735,6 +735,7 @@ static void take_over_work(struct ehca_comp_pool *pool, } +#ifdef CONFIG_HOTPLUG_CPU static int comp_pool_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index c3f99f33b49c..fe90e7454560 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch "); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0023"); +MODULE_VERSION("SVNEHCA_0022"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -62,7 +62,7 @@ int ehca_use_hp_mr = 0; int ehca_port_act_time = 30; int ehca_poll_all_eqs = 1; int ehca_static_rate = -1; -int ehca_scaling_code = 0; +int ehca_scaling_code = 1; module_param_named(open_aqp1, ehca_open_aqp1, int, 0); module_param_named(debug_level, ehca_debug_level, int, 0); @@ -98,7 +98,6 @@ MODULE_PARM_DESC(scaling_code, spinlock_t ehca_qp_idr_lock; spinlock_t ehca_cq_idr_lock; -spinlock_t hcall_lock; DEFINE_IDR(ehca_qp_idr); DEFINE_IDR(ehca_cq_idr); @@ -454,14 +453,15 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp, DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR, ehca_show_debug_level, ehca_store_debug_level); -static struct attribute *ehca_drv_attrs[] = { - &driver_attr_debug_level.attr, - NULL -}; +void ehca_create_driver_sysfs(struct ibmebus_driver *drv) +{ + driver_create_file(&drv->driver, &driver_attr_debug_level); +} -static struct attribute_group ehca_drv_attr_grp = { - .attrs = ehca_drv_attrs -}; +void ehca_remove_driver_sysfs(struct ibmebus_driver *drv) +{ + driver_remove_file(&drv->driver, &driver_attr_debug_level); +} #define EHCA_RESOURCE_ATTR(name) \ static ssize_t ehca_show_##name(struct device *dev, \ @@ -523,28 +523,44 @@ static ssize_t ehca_show_adapter_handle(struct device *dev, } static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL); -static struct attribute *ehca_dev_attrs[] = { - &dev_attr_adapter_handle.attr, - &dev_attr_num_ports.attr, - &dev_attr_hw_ver.attr, - &dev_attr_max_eq.attr, - &dev_attr_cur_eq.attr, - &dev_attr_max_cq.attr, - &dev_attr_cur_cq.attr, - &dev_attr_max_qp.attr, - &dev_attr_cur_qp.attr, - &dev_attr_max_mr.attr, - &dev_attr_cur_mr.attr, - &dev_attr_max_mw.attr, - &dev_attr_cur_mw.attr, - &dev_attr_max_pd.attr, - &dev_attr_max_ah.attr, - NULL -}; -static struct attribute_group ehca_dev_attr_grp = { - .attrs = ehca_dev_attrs -}; +void ehca_create_device_sysfs(struct ibmebus_dev *dev) +{ + device_create_file(&dev->ofdev.dev, &dev_attr_adapter_handle); + device_create_file(&dev->ofdev.dev, &dev_attr_num_ports); + device_create_file(&dev->ofdev.dev, &dev_attr_hw_ver); + device_create_file(&dev->ofdev.dev, &dev_attr_max_eq); + device_create_file(&dev->ofdev.dev, &dev_attr_cur_eq); + device_create_file(&dev->ofdev.dev, &dev_attr_max_cq); + device_create_file(&dev->ofdev.dev, &dev_attr_cur_cq); + device_create_file(&dev->ofdev.dev, &dev_attr_max_qp); + device_create_file(&dev->ofdev.dev, &dev_attr_cur_qp); + device_create_file(&dev->ofdev.dev, &dev_attr_max_mr); + device_create_file(&dev->ofdev.dev, &dev_attr_cur_mr); + device_create_file(&dev->ofdev.dev, &dev_attr_max_mw); + device_create_file(&dev->ofdev.dev, &dev_attr_cur_mw); + device_create_file(&dev->ofdev.dev, &dev_attr_max_pd); + device_create_file(&dev->ofdev.dev, &dev_attr_max_ah); +} + +void ehca_remove_device_sysfs(struct ibmebus_dev *dev) +{ + device_remove_file(&dev->ofdev.dev, &dev_attr_adapter_handle); + device_remove_file(&dev->ofdev.dev, &dev_attr_num_ports); + device_remove_file(&dev->ofdev.dev, &dev_attr_hw_ver); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_eq); + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_eq); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_cq); + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_cq); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_qp); + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_qp); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_mr); + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mr); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_mw); + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mw); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_pd); + device_remove_file(&dev->ofdev.dev, &dev_attr_max_ah); +} static int __devinit ehca_probe(struct ibmebus_dev *dev, const struct of_device_id *id) @@ -652,10 +668,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, } } - ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); - if (ret) /* only complain; we can live without attributes */ - ehca_err(&shca->ib_device, - "Cannot create device attributes ret=%d", ret); + ehca_create_device_sysfs(dev); spin_lock(&shca_list_lock); list_add(&shca->shca_list, &shca_list); @@ -707,7 +720,7 @@ static int __devexit ehca_remove(struct ibmebus_dev *dev) struct ehca_shca *shca = dev->ofdev.dev.driver_data; int ret; - sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); + ehca_remove_device_sysfs(dev); if (ehca_open_aqp1 == 1) { int i; @@ -799,12 +812,11 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0023)\n"); + "(Rel.: SVNEHCA_0022)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); spin_lock_init(&ehca_cq_idr_lock); - spin_lock_init(&hcall_lock); INIT_LIST_HEAD(&shca_list); spin_lock_init(&shca_list_lock); @@ -826,9 +838,7 @@ int __init ehca_module_init(void) goto module_init2; } - ret = sysfs_create_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp); - if (ret) /* only complain; we can live without attributes */ - ehca_gen_err("Cannot create driver attributes ret=%d", ret); + ehca_create_driver_sysfs(&ehca_driver); if (ehca_poll_all_eqs != 1) { ehca_gen_err("WARNING!!!"); @@ -855,7 +865,7 @@ void __exit ehca_module_exit(void) if (ehca_poll_all_eqs == 1) del_timer_sync(&poll_eqs_timer); - sysfs_remove_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp); + ehca_remove_driver_sysfs(&ehca_driver); ibmebus_unregister_driver(&ehca_driver); ehca_destroy_slab_caches(); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c index b5bc787c77b6..df0516f24379 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c @@ -523,8 +523,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, goto create_qp_exit1; } - my_qp->ib_qp.qp_num = my_qp->real_qp_num; - switch (init_attr->qp_type) { case IB_QPT_RC: if (isdaqp == 0) { @@ -570,7 +568,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr; parms.act_nr_send_sges = init_attr->cap.max_send_sge; parms.act_nr_recv_sges = init_attr->cap.max_recv_sge; - my_qp->ib_qp.qp_num = + my_qp->real_qp_num = (init_attr->qp_type == IB_QPT_SMI) ? 0 : 1; } @@ -597,6 +595,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, my_qp->ib_qp.recv_cq = init_attr->recv_cq; my_qp->ib_qp.send_cq = init_attr->send_cq; + my_qp->ib_qp.qp_num = my_qp->real_qp_num; my_qp->ib_qp.qp_type = init_attr->qp_type; my_qp->qp_type = init_attr->qp_type; @@ -969,21 +968,17 @@ static int internal_modify_qp(struct ib_qp *ibqp, ((ehca_mult - 1) / ah_mult) : 0; else mqpcb->max_static_rate = 0; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); - /* - * Always supply the GRH flag, even if it's zero, to give the - * hypervisor a clear "yes" or "no" instead of a "perhaps" - */ - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); /* * only if GRH is TRUE we might consider SOURCE_GID_IDX * and DEST_GID otherwise phype will return H_ATTR_PARM!!! */ if (attr->ah_attr.ah_flags == IB_AH_GRH) { - mqpcb->send_grh_flag = 1; - + mqpcb->send_grh_flag = 1 << 31; + update_mask |= + EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1); diff --git a/trunk/drivers/infiniband/hw/ehca/hcp_if.c b/trunk/drivers/infiniband/hw/ehca/hcp_if.c index 7f0beec74f70..b564fcd3b282 100644 --- a/trunk/drivers/infiniband/hw/ehca/hcp_if.c +++ b/trunk/drivers/infiniband/hw/ehca/hcp_if.c @@ -154,8 +154,7 @@ static long ehca_plpar_hcall9(unsigned long opcode, unsigned long arg9) { long ret; - int i, sleep_msecs, lock_is_set = 0; - unsigned long flags; + int i, sleep_msecs; ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx " "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx", @@ -163,18 +162,10 @@ static long ehca_plpar_hcall9(unsigned long opcode, arg8, arg9); for (i = 0; i < 5; i++) { - if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) { - spin_lock_irqsave(&hcall_lock, flags); - lock_is_set = 1; - } - ret = plpar_hcall9(opcode, outs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - if (lock_is_set) - spin_unlock_irqrestore(&hcall_lock, flags); - if (H_IS_LONG_BUSY(ret)) { sleep_msecs = get_longbusy_msecs(ret); msleep_interruptible(sleep_msecs); @@ -202,11 +193,11 @@ static long ehca_plpar_hcall9(unsigned long opcode, opcode, ret, outs[0], outs[1], outs[2], outs[3], outs[4], outs[5], outs[6], outs[7], outs[8]); return ret; + } return H_BUSY; } - u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, struct ehca_pfeq *pfeq, const u32 neq_control, diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c index 4e2e3dfeb2c8..1b9c30857754 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c @@ -747,6 +747,7 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd) static int ipath_pe_intconfig(struct ipath_devdata *dd) { + u64 val; u32 chiprev; /* @@ -759,9 +760,9 @@ static int ipath_pe_intconfig(struct ipath_devdata *dd) if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) { /* Rev2+ reports extra errors via internal GPIO pins */ dd->ipath_flags |= IPATH_GPIO_ERRINTRS; - dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK; - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); + val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask); + val |= IPATH_GPIO_ERRINTR_MASK; + ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val); } return 0; } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c index a90d3b5699c4..45d033169c6e 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c @@ -1056,7 +1056,7 @@ irqreturn_t ipath_intr(int irq, void *data) gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT); chk0rcv = 1; } - if (gpiostatus) { + if (unlikely(gpiostatus)) { /* * Some unexpected bits remain. If they could have * caused the interrupt, complain and clear. @@ -1065,8 +1065,9 @@ irqreturn_t ipath_intr(int irq, void *data) * GPIO interrupts, possibly on a "three strikes" * basis. */ - const u32 mask = (u32) dd->ipath_gpio_mask; - + u32 mask; + mask = ipath_read_kreg32( + dd, dd->ipath_kregs->kr_gpio_mask); if (mask & gpiostatus) { ipath_dbg("Unexpected GPIO IRQ bits %x\n", gpiostatus & mask); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h index 12194f3dd8cc..e900c2593f44 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -397,8 +397,6 @@ struct ipath_devdata { unsigned long ipath_pioavailshadow[8]; /* shadow of kr_gpio_out, for rmw ops */ u64 ipath_gpio_out; - /* shadow the gpio mask register */ - u64 ipath_gpio_mask; /* kr_revision shadow */ u64 ipath_revision; /* diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c index bb70845279b8..12933e77c7e9 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -1387,12 +1387,13 @@ static int enable_timer(struct ipath_devdata *dd) * processing. */ if (dd->ipath_flags & IPATH_GPIO_INTR) { + u64 val; ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect, 0x2074076542310ULL); /* Enable GPIO bit 2 interrupt */ - dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT); - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); + val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask); + val |= (u64) (1 << IPATH_GPIO_PORT0_BIT); + ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val); } init_timer(&dd->verbs_timer); @@ -1411,9 +1412,8 @@ static int disable_timer(struct ipath_devdata *dd) u64 val; /* Disable GPIO bit 2 interrupt */ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask); - dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT)); - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); + val &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT)); + ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val); /* * We might want to undo changes to debugportselect, * but how? diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index 402f3a20ec0a..688ecb4c39f3 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -489,7 +489,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); if (!ibdev->uar_map) goto err_uar; - MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); INIT_LIST_HEAD(&ibdev->pgdir_list); mutex_init(&ibdev->pgdir_mutex); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c index ca224d018af2..cf0868f6e965 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c @@ -284,7 +284,7 @@ void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn, { struct mthca_cqe *cqe; u32 prod_index; - int i, nfreed = 0; + int nfreed = 0; spin_lock_irq(&cq->lock); @@ -321,8 +321,6 @@ void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn, } if (nfreed) { - for (i = 0; i < nfreed; ++i) - set_cqe_hw(get_cqe(cq, (cq->cons_index + i) & cq->ibcq.cqe)); wmb(); cq->cons_index += nfreed; update_cons_index(dev, cq, nfreed); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c index 72fabb822f1c..fee60c852d14 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1862,7 +1862,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, dev->kar + MTHCA_RECEIVE_DOORBELL, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); - qp->rq.next_ind = ind; qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB; size0 = 0; } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c index eec833b81e9b..785bc8505f2a 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -257,11 +257,10 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even cm_id->context = p; p->jiffies = jiffies; spin_lock_irq(&priv->lock); - if (list_empty(&priv->cm.passive_ids)) - queue_delayed_work(ipoib_workqueue, - &priv->cm.stale_task, IPOIB_CM_RX_DELAY); list_add(&p->list, &priv->cm.passive_ids); spin_unlock_irq(&priv->lock); + queue_delayed_work(ipoib_workqueue, + &priv->cm.stale_task, IPOIB_CM_RX_DELAY); return 0; err_rep: @@ -379,6 +378,8 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) if (!list_empty(&p->list)) list_move(&p->list, &priv->cm.passive_ids); spin_unlock_irqrestore(&priv->lock, flags); + queue_delayed_work(ipoib_workqueue, + &priv->cm.stale_task, IPOIB_CM_RX_DELAY); } } @@ -1099,10 +1100,6 @@ static void ipoib_cm_stale_task(struct work_struct *work) kfree(p); spin_lock_irq(&priv->lock); } - - if (!list_empty(&priv->cm.passive_ids)) - queue_delayed_work(ipoib_workqueue, - &priv->cm.stale_task, IPOIB_CM_RX_DELAY); spin_unlock_irq(&priv->lock); } diff --git a/trunk/drivers/mmc/card/block.c b/trunk/drivers/mmc/card/block.c index a7562f7fc0b3..d24ab234394c 100644 --- a/trunk/drivers/mmc/card/block.c +++ b/trunk/drivers/mmc/card/block.c @@ -45,6 +45,8 @@ */ #define MMC_SHIFT 3 +static int major; + /* * There is one mmc_blk_data per slot. */ @@ -464,7 +466,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) md->queue.issue_fn = mmc_blk_issue_rq; md->queue.data = md; - md->disk->major = MMC_BLOCK_MAJOR; + md->disk->major = major; md->disk->first_minor = devidx << MMC_SHIFT; md->disk->fops = &mmc_bdops; md->disk->private_data = md; @@ -632,9 +634,14 @@ static int __init mmc_blk_init(void) { int res = -ENOMEM; - res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); - if (res) + res = register_blkdev(major, "mmc"); + if (res < 0) { + printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n", + major, res); goto out; + } + if (major == 0) + major = res; return mmc_register_driver(&mmc_driver); @@ -645,7 +652,7 @@ static int __init mmc_blk_init(void) static void __exit mmc_blk_exit(void) { mmc_unregister_driver(&mmc_driver); - unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); + unregister_blkdev(major, "mmc"); } module_init(mmc_blk_init); @@ -654,3 +661,5 @@ module_exit(mmc_blk_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); +module_param(major, int, 0444); +MODULE_PARM_DESC(major, "specify the major device number for MMC block driver"); diff --git a/trunk/drivers/mmc/host/au1xmmc.c b/trunk/drivers/mmc/host/au1xmmc.c index f967226d7505..b7156a4555b5 100644 --- a/trunk/drivers/mmc/host/au1xmmc.c +++ b/trunk/drivers/mmc/host/au1xmmc.c @@ -187,8 +187,9 @@ static void au1xmmc_tasklet_finish(unsigned long param) } static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, - struct mmc_command *cmd, unsigned int flags) + struct mmc_command *cmd) { + u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); switch (mmc_resp_type(cmd)) { @@ -212,16 +213,24 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, return MMC_ERR_INVALID; } - if (flags & MMC_DATA_READ) { - if (flags & MMC_DATA_MULTI) - mmccmd |= SD_CMD_CT_4; - else - mmccmd |= SD_CMD_CT_2; - } else if (flags & MMC_DATA_WRITE) { - if (flags & MMC_DATA_MULTI) - mmccmd |= SD_CMD_CT_3; - else - mmccmd |= SD_CMD_CT_1; + switch(cmd->opcode) { + case MMC_READ_SINGLE_BLOCK: + case SD_APP_SEND_SCR: + mmccmd |= SD_CMD_CT_2; + break; + case MMC_READ_MULTIPLE_BLOCK: + mmccmd |= SD_CMD_CT_4; + break; + case MMC_WRITE_BLOCK: + mmccmd |= SD_CMD_CT_1; + break; + + case MMC_WRITE_MULTIPLE_BLOCK: + mmccmd |= SD_CMD_CT_3; + break; + case MMC_STOP_TRANSMISSION: + mmccmd |= SD_CMD_CT_7; + break; } au_writel(cmd->arg, HOST_CMDARG(host)); @@ -656,7 +665,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) { struct au1xmmc_host *host = mmc_priv(mmc); - unsigned int flags = 0; int ret = MMC_ERR_NONE; WARN_ON(irqs_disabled()); @@ -669,12 +677,11 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) if (mrq->data) { FLUSH_FIFO(host); - flags = mrq->data->flags; ret = au1xmmc_prepare_data(host, mrq->data); } if (ret == MMC_ERR_NONE) - ret = au1xmmc_send_command(host, 0, mrq->cmd, flags); + ret = au1xmmc_send_command(host, 0, mrq->cmd); if (ret != MMC_ERR_NONE) { mrq->cmd->error = ret; diff --git a/trunk/drivers/mmc/host/pxamci.c b/trunk/drivers/mmc/host/pxamci.c index f8985c508bb9..d97d3864b57f 100644 --- a/trunk/drivers/mmc/host/pxamci.c +++ b/trunk/drivers/mmc/host/pxamci.c @@ -232,14 +232,20 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) /* * workaround for erratum #42: * Intel PXA27x Family Processor Specification Update Rev 001 - * A bogus CRC error can appear if the msb of a 136 bit - * response is a one. */ - if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) { - pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); - } else -#endif + if (cmd->opcode == MMC_ALL_SEND_CID || + cmd->opcode == MMC_SEND_CSD || + cmd->opcode == MMC_SEND_CID) { + /* a bogus CRC error can appear if the msb of + the 15 byte response is a one */ + if ((cmd->resp[0] & 0x80000000) == 0) + cmd->error = MMC_ERR_BADCRC; + } else { + pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode); + } +#else cmd->error = MMC_ERR_BADCRC; +#endif } pxamci_disable_irq(host, END_CMD_RES); diff --git a/trunk/drivers/mmc/host/sdhci.c b/trunk/drivers/mmc/host/sdhci.c index a359efdd77eb..ff5bf73cdd25 100644 --- a/trunk/drivers/mmc/host/sdhci.c +++ b/trunk/drivers/mmc/host/sdhci.c @@ -963,15 +963,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) sdhci_transfer_pio(host); - /* - * We currently don't do anything fancy with DMA - * boundaries, but as we can't disable the feature - * we need to at least restart the transfer. - */ - if (intmask & SDHCI_INT_DMA_END) - writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), - host->ioaddr + SDHCI_DMA_ADDRESS); - if (intmask & SDHCI_INT_DATA_END) sdhci_finish_data(host); } diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index c5baa197bc08..fb99cd445504 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2508,7 +2508,6 @@ config MLX4_CORE config MLX4_DEBUG bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED) - depends on MLX4_CORE default y ---help--- This option causes debugging code to be compiled into the diff --git a/trunk/drivers/net/mlx4/main.c b/trunk/drivers/net/mlx4/main.c index 20b8c0d3ced4..4debb024eaf9 100644 --- a/trunk/drivers/net/mlx4/main.c +++ b/trunk/drivers/net/mlx4/main.c @@ -542,6 +542,8 @@ static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int err; + MLX4_INIT_DOORBELL_LOCK(&priv->doorbell_lock); + err = mlx4_init_uar_table(dev); if (err) { mlx4_err(dev, "Failed to initialize " diff --git a/trunk/drivers/net/mlx4/mlx4.h b/trunk/drivers/net/mlx4/mlx4.h index 3d3b6d24d8d3..9befbae3d196 100644 --- a/trunk/drivers/net/mlx4/mlx4.h +++ b/trunk/drivers/net/mlx4/mlx4.h @@ -275,6 +275,7 @@ struct mlx4_priv { struct mlx4_uar driver_uar; void __iomem *kar; + MLX4_DECLARE_DOORBELL_LOCK(doorbell_lock) u32 rev_id; char board_id[MLX4_BOARD_ID_LEN]; diff --git a/trunk/drivers/sbus/char/bbc_i2c.c b/trunk/drivers/sbus/char/bbc_i2c.c index 178155bf9db6..8410587348f1 100644 --- a/trunk/drivers/sbus/char/bbc_i2c.c +++ b/trunk/drivers/sbus/char/bbc_i2c.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "bbc_i2c.h" diff --git a/trunk/drivers/sbus/char/display7seg.c b/trunk/drivers/sbus/char/display7seg.c index 3279a1b6501d..2d14a29effe4 100644 --- a/trunk/drivers/sbus/char/display7seg.c +++ b/trunk/drivers/sbus/char/display7seg.c @@ -20,7 +20,6 @@ #include /* EBus device */ #include /* OpenProm Library */ #include /* put_/get_user */ -#include #include diff --git a/trunk/drivers/scsi/Kconfig b/trunk/drivers/scsi/Kconfig index d28c14e23c32..e62d23f65180 100644 --- a/trunk/drivers/scsi/Kconfig +++ b/trunk/drivers/scsi/Kconfig @@ -1757,14 +1757,6 @@ config SCSI_ESP_CORE tristate "ESP Scsi Driver Core" depends on SCSI select SCSI_SPI_ATTRS - help - This is a core driver for NCR53c9x based scsi chipsets, - also known as "ESP" for Emulex Scsi Processor or - Enhanced Scsi Processor. This driver does not exist by - itself, there are front-end drivers which, when enabled, - select and enable this driver. One example is SCSI_SUNESP. - These front-end drivers provide probing, DMA, and register - access support for the core driver. config SCSI_SUNESP tristate "Sparc ESP Scsi Driver" diff --git a/trunk/drivers/serial/sunhv.c b/trunk/drivers/serial/sunhv.c index c3a6bd2e7950..40d48566215c 100644 --- a/trunk/drivers/serial/sunhv.c +++ b/trunk/drivers/serial/sunhv.c @@ -493,10 +493,6 @@ static struct of_device_id hv_match[] = { .name = "console", .compatible = "qcn", }, - { - .name = "console", - .compatible = "SUNW,sun4v-console", - }, {}, }; MODULE_DEVICE_TABLE(of, hv_match); diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 4d7485fa553f..eebcb708cff1 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -1535,7 +1535,7 @@ config FB_LEO config FB_XVR500 bool "Sun XVR-500 3DLABS Wildcat support" - depends on (FB = y) && PCI && SPARC64 + depends on FB && PCI && SPARC64 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1548,7 +1548,7 @@ config FB_XVR500 config FB_XVR2500 bool "Sun XVR-2500 3DLABS Wildcat support" - depends on (FB = y) && PCI && SPARC64 + depends on FB && PCI && SPARC64 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/trunk/fs/eventpoll.c b/trunk/fs/eventpoll.c index 0b73cd45a06d..1aad34ea61a4 100644 --- a/trunk/fs/eventpoll.c +++ b/trunk/fs/eventpoll.c @@ -1,6 +1,6 @@ /* - * fs/eventpoll.c (Efficent event polling implementation) - * Copyright (C) 2001,...,2007 Davide Libenzi + * fs/eventpoll.c ( Efficent event polling implementation ) + * Copyright (C) 2001,...,2006 Davide Libenzi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -38,14 +39,15 @@ #include #include #include +#include /* * LOCKING: * There are three level of locking required by epoll : * * 1) epmutex (mutex) - * 2) ep->mtx (mutex) - * 3) ep->lock (spinlock) + * 2) ep->sem (rw_semaphore) + * 3) ep->lock (rw_lock) * * The acquire order is the one listed above, from 1 to 3. * We need a spinlock (ep->lock) because we manipulate objects @@ -55,20 +57,20 @@ * a spinlock. During the event transfer loop (from kernel to * user space) we could end up sleeping due a copy_to_user(), so * we need a lock that will allow us to sleep. This lock is a - * mutex (ep->mtx). It is acquired during the event transfer loop, - * during epoll_ctl(EPOLL_CTL_DEL) and during eventpoll_release_file(). - * Then we also need a global mutex to serialize eventpoll_release_file() - * and ep_free(). - * This mutex is acquired by ep_free() during the epoll file + * read-write semaphore (ep->sem). It is acquired on read during + * the event transfer loop and in write during epoll_ctl(EPOLL_CTL_DEL) + * and during eventpoll_release_file(). Then we also need a global + * semaphore to serialize eventpoll_release_file() and ep_free(). + * This semaphore is acquired by ep_free() during the epoll file * cleanup path and it is also acquired by eventpoll_release_file() * if a file has been pushed inside an epoll set and it is then * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL). - * It is possible to drop the "ep->mtx" and to use the global - * mutex "epmutex" (together with "ep->lock") to have it working, - * but having "ep->mtx" will make the interface more scalable. + * It is possible to drop the "ep->sem" and to use the global + * semaphore "epmutex" (together with "ep->lock") to have it working, + * but having "ep->sem" will make the interface more scalable. * Events that require holding "epmutex" are very rare, while for - * normal operations the epoll private "ep->mtx" will guarantee - * a better scalability. + * normal operations the epoll private "ep->sem" will guarantee + * a greater scalability. */ #define DEBUG_EPOLL 0 @@ -100,8 +102,6 @@ #define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) -#define EP_UNACTIVE_PTR ((void *) -1L) - struct epoll_filefd { struct file *file; int fd; @@ -111,7 +111,7 @@ struct epoll_filefd { * Node that is linked into the "wake_task_list" member of the "struct poll_safewake". * It is used to keep track on all tasks that are currently inside the wake_up() code * to 1) short-circuit the one coming from the same task and same wait queue head - * (loop) 2) allow a maximum number of epoll descriptors inclusion nesting + * ( loop ) 2) allow a maximum number of epoll descriptors inclusion nesting * 3) let go the ones coming from other tasks. */ struct wake_task_node { @@ -129,42 +129,6 @@ struct poll_safewake { spinlock_t lock; }; -/* - * Each file descriptor added to the eventpoll interface will - * have an entry of this type linked to the "rbr" RB tree. - */ -struct epitem { - /* RB tree node used to link this structure to the eventpoll RB tree */ - struct rb_node rbn; - - /* List header used to link this structure to the eventpoll ready list */ - struct list_head rdllink; - - /* - * Works together "struct eventpoll"->ovflist in keeping the - * single linked chain of items. - */ - struct epitem *next; - - /* The file descriptor information this item refers to */ - struct epoll_filefd ffd; - - /* Number of active wait queue attached to poll operations */ - int nwait; - - /* List containing poll wait queues */ - struct list_head pwqlist; - - /* The "container" of this item */ - struct eventpoll *ep; - - /* List header used to link this item to the "struct file" items list */ - struct list_head fllink; - - /* The structure that describe the interested events and the source fd */ - struct epoll_event event; -}; - /* * This structure is stored inside the "private_data" member of the file * structure and rapresent the main data sructure for the eventpoll @@ -172,15 +136,15 @@ struct epitem { */ struct eventpoll { /* Protect the this structure access */ - spinlock_t lock; + rwlock_t lock; /* - * This mutex is used to ensure that files are not removed - * while epoll is using them. This is held during the event - * collection loop, the file cleanup path, the epoll file exit - * code and the ctl operations. + * This semaphore is used to ensure that files are not removed + * while epoll is using them. This is read-held during the event + * collection loop and it is write-held during the file cleanup + * path, the epoll file exit code and the ctl operations. */ - struct mutex mtx; + struct rw_semaphore sem; /* Wait queue used by sys_epoll_wait() */ wait_queue_head_t wq; @@ -191,15 +155,8 @@ struct eventpoll { /* List of ready file descriptors */ struct list_head rdllist; - /* RB tree root used to store monitored fd structs */ + /* RB-Tree root used to store monitored fd structs */ struct rb_root rbr; - - /* - * This is a single linked list that chains all the "struct epitem" that - * happened while transfering ready events to userspace w/out - * holding ->lock. - */ - struct epitem *ovflist; }; /* Wait structure used by the poll hooks */ @@ -220,6 +177,42 @@ struct eppoll_entry { wait_queue_head_t *whead; }; +/* + * Each file descriptor added to the eventpoll interface will + * have an entry of this type linked to the "rbr" RB tree. + */ +struct epitem { + /* RB-Tree node used to link this structure to the eventpoll rb-tree */ + struct rb_node rbn; + + /* List header used to link this structure to the eventpoll ready list */ + struct list_head rdllink; + + /* The file descriptor information this item refers to */ + struct epoll_filefd ffd; + + /* Number of active wait queue attached to poll operations */ + int nwait; + + /* List containing poll wait queues */ + struct list_head pwqlist; + + /* The "container" of this item */ + struct eventpoll *ep; + + /* The structure that describe the interested events and the source fd */ + struct epoll_event event; + + /* + * Used to keep track of the usage count of the structure. This avoids + * that the structure will desappear from underneath our processing. + */ + atomic_t usecnt; + + /* List header used to link this item to the "struct file" items list */ + struct list_head fllink; +}; + /* Wrapper struct used by poll queueing */ struct ep_pqueue { poll_table pt; @@ -227,7 +220,7 @@ struct ep_pqueue { }; /* - * This mutex is used to serialize ep_free() and eventpoll_release_file(). + * This semaphore is used to serialize ep_free() and eventpoll_release_file(). */ static struct mutex epmutex; @@ -241,7 +234,7 @@ static struct kmem_cache *epi_cache __read_mostly; static struct kmem_cache *pwq_cache __read_mostly; -/* Setup the structure that is used as key for the RB tree */ +/* Setup the structure that is used as key for the rb-tree */ static inline void ep_set_ffd(struct epoll_filefd *ffd, struct file *file, int fd) { @@ -249,7 +242,7 @@ static inline void ep_set_ffd(struct epoll_filefd *ffd, ffd->fd = fd; } -/* Compare RB tree keys */ +/* Compare rb-tree keys */ static inline int ep_cmp_ffd(struct epoll_filefd *p1, struct epoll_filefd *p2) { @@ -257,20 +250,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1, (p1->file < p2->file ? -1 : p1->fd - p2->fd)); } -/* Special initialization for the RB tree node to detect linkage */ +/* Special initialization for the rb-tree node to detect linkage */ static inline void ep_rb_initnode(struct rb_node *n) { rb_set_parent(n, n); } -/* Removes a node from the RB tree and marks it for a fast is-linked check */ +/* Removes a node from the rb-tree and marks it for a fast is-linked check */ static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r) { rb_erase(n, r); rb_set_parent(n, n); } -/* Fast check to verify that the item is linked to the main RB tree */ +/* Fast check to verify that the item is linked to the main rb-tree */ static inline int ep_rb_linked(struct rb_node *n) { return rb_parent(n) != n; @@ -387,12 +380,79 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) } } +/* + * Unlink the "struct epitem" from all places it might have been hooked up. + * This function must be called with write IRQ lock on "ep->lock". + */ +static int ep_unlink(struct eventpoll *ep, struct epitem *epi) +{ + int error; + + /* + * It can happen that this one is called for an item already unlinked. + * The check protect us from doing a double unlink ( crash ). + */ + error = -ENOENT; + if (!ep_rb_linked(&epi->rbn)) + goto error_return; + + /* + * Clear the event mask for the unlinked item. This will avoid item + * notifications to be sent after the unlink operation from inside + * the kernel->userspace event transfer loop. + */ + epi->event.events = 0; + + /* + * At this point is safe to do the job, unlink the item from our rb-tree. + * This operation togheter with the above check closes the door to + * double unlinks. + */ + ep_rb_erase(&epi->rbn, &ep->rbr); + + /* + * If the item we are going to remove is inside the ready file descriptors + * we want to remove it from this list to avoid stale events. + */ + if (ep_is_linked(&epi->rdllink)) + list_del_init(&epi->rdllink); + + error = 0; +error_return: + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n", + current, ep, epi->ffd.file, error)); + + return error; +} + +/* + * Increment the usage count of the "struct epitem" making it sure + * that the user will have a valid pointer to reference. + */ +static void ep_use_epitem(struct epitem *epi) +{ + atomic_inc(&epi->usecnt); +} + +/* + * Decrement ( release ) the usage count by signaling that the user + * has finished using the structure. It might lead to freeing the + * structure itself if the count goes to zero. + */ +static void ep_release_epitem(struct epitem *epi) +{ + if (atomic_dec_and_test(&epi->usecnt)) + kmem_cache_free(epi_cache, epi); +} + /* * Removes a "struct epitem" from the eventpoll RB tree and deallocates - * all the associated resources. Must be called with "mtx" held. + * all the associated resources. */ static int ep_remove(struct eventpoll *ep, struct epitem *epi) { + int error; unsigned long flags; struct file *file = epi->ffd.file; @@ -412,21 +472,26 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) list_del_init(&epi->fllink); spin_unlock(&file->f_ep_lock); - if (ep_rb_linked(&epi->rbn)) - ep_rb_erase(&epi->rbn, &ep->rbr); + /* We need to acquire the write IRQ lock before calling ep_unlink() */ + write_lock_irqsave(&ep->lock, flags); - spin_lock_irqsave(&ep->lock, flags); - if (ep_is_linked(&epi->rdllink)) - list_del_init(&epi->rdllink); - spin_unlock_irqrestore(&ep->lock, flags); + /* Really unlink the item from the RB tree */ + error = ep_unlink(ep, epi); + + write_unlock_irqrestore(&ep->lock, flags); + + if (error) + goto error_return; /* At this point it is safe to free the eventpoll item */ - kmem_cache_free(epi_cache, epi); + ep_release_epitem(epi); - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p)\n", - current, ep, file)); + error = 0; +error_return: + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n", + current, ep, file, error)); - return 0; + return error; } static void ep_free(struct eventpoll *ep) @@ -441,7 +506,7 @@ static void ep_free(struct eventpoll *ep) /* * We need to lock this because we could be hit by * eventpoll_release_file() while we're freeing the "struct eventpoll". - * We do not need to hold "ep->mtx" here because the epoll file + * We do not need to hold "ep->sem" here because the epoll file * is on the way to be removed and no one has references to it * anymore. The only hit might come from eventpoll_release_file() but * holding "epmutex" is sufficent here. @@ -460,7 +525,7 @@ static void ep_free(struct eventpoll *ep) /* * Walks through the whole tree by freeing each "struct epitem". At this * point we are sure no poll callbacks will be lingering around, and also by - * holding "epmutex" we can be sure that no file cleanup code will hit + * write-holding "sem" we can be sure that no file cleanup code will hit * us during this operation. So we can avoid the lock on "ep->lock". */ while ((rbp = rb_first(&ep->rbr)) != 0) { @@ -469,16 +534,16 @@ static void ep_free(struct eventpoll *ep) } mutex_unlock(&epmutex); - mutex_destroy(&ep->mtx); - kfree(ep); } static int ep_eventpoll_release(struct inode *inode, struct file *file) { struct eventpoll *ep = file->private_data; - if (ep) + if (ep) { ep_free(ep); + kfree(ep); + } DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep)); return 0; @@ -494,10 +559,10 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) poll_wait(file, &ep->poll_wait, wait); /* Check our condition */ - spin_lock_irqsave(&ep->lock, flags); + read_lock_irqsave(&ep->lock, flags); if (!list_empty(&ep->rdllist)) pollflags = POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ep->lock, flags); + read_unlock_irqrestore(&ep->lock, flags); return pollflags; } @@ -529,11 +594,9 @@ void eventpoll_release_file(struct file *file) * We don't want to get "file->f_ep_lock" because it is not * necessary. It is not necessary because we're in the "struct file" * cleanup path, and this means that noone is using this file anymore. - * So, for example, epoll_ctl() cannot hit here sicne if we reach this - * point, the file counter already went to zero and fget() would fail. - * The only hit might come from ep_free() but by holding the mutex + * The only hit might come from ep_free() but by holding the semaphore * will correctly serialize the operation. We do need to acquire - * "ep->mtx" after "epmutex" because ep_remove() requires it when called + * "ep->sem" after "epmutex" because ep_remove() requires it when called * from anywhere but ep_free(). */ mutex_lock(&epmutex); @@ -543,9 +606,9 @@ void eventpoll_release_file(struct file *file) ep = epi->ep; list_del_init(&epi->fllink); - mutex_lock(&ep->mtx); + down_write(&ep->sem); ep_remove(ep, epi); - mutex_unlock(&ep->mtx); + up_write(&ep->sem); } mutex_unlock(&epmutex); @@ -558,13 +621,12 @@ static int ep_alloc(struct eventpoll **pep) if (!ep) return -ENOMEM; - spin_lock_init(&ep->lock); - mutex_init(&ep->mtx); + rwlock_init(&ep->lock); + init_rwsem(&ep->sem); init_waitqueue_head(&ep->wq); init_waitqueue_head(&ep->poll_wait); INIT_LIST_HEAD(&ep->rdllist); ep->rbr = RB_ROOT; - ep->ovflist = EP_UNACTIVE_PTR; *pep = ep; @@ -574,18 +636,20 @@ static int ep_alloc(struct eventpoll **pep) } /* - * Search the file inside the eventpoll tree. The RB tree operations - * are protected by the "mtx" mutex, and ep_find() must be called with - * "mtx" held. + * Search the file inside the eventpoll tree. It add usage count to + * the returned item, so the caller must call ep_release_epitem() + * after finished using the "struct epitem". */ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd) { int kcmp; + unsigned long flags; struct rb_node *rbp; struct epitem *epi, *epir = NULL; struct epoll_filefd ffd; ep_set_ffd(&ffd, file, fd); + read_lock_irqsave(&ep->lock, flags); for (rbp = ep->rbr.rb_node; rbp; ) { epi = rb_entry(rbp, struct epitem, rbn); kcmp = ep_cmp_ffd(&ffd, &epi->ffd); @@ -594,10 +658,12 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd) else if (kcmp < 0) rbp = rbp->rb_left; else { + ep_use_epitem(epi); epir = epi; break; } } + read_unlock_irqrestore(&ep->lock, flags); DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_find(%p) -> %p\n", current, file, epir)); @@ -620,7 +686,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", current, epi->ffd.file, epi, ep)); - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); /* * If the event mask does not contain any poll(2) event, we consider the @@ -629,21 +695,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k * until the next EPOLL_CTL_MOD will be issued. */ if (!(epi->event.events & ~EP_PRIVATE_BITS)) - goto out_unlock; - - /* - * If we are trasfering events to userspace, we can hold no locks - * (because we're accessing user memory, and because of linux f_op->poll() - * semantics). All the events that happens during that period of time are - * chained in ep->ovflist and requeued later on. - */ - if (unlikely(ep->ovflist != EP_UNACTIVE_PTR)) { - if (epi->next == EP_UNACTIVE_PTR) { - epi->next = ep->ovflist; - ep->ovflist = epi; - } - goto out_unlock; - } + goto is_disabled; /* If this file is already in the ready list we exit soon */ if (ep_is_linked(&epi->rdllink)) @@ -662,8 +714,8 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k if (waitqueue_active(&ep->poll_wait)) pwake++; -out_unlock: - spin_unlock_irqrestore(&ep->lock, flags); +is_disabled: + write_unlock_irqrestore(&ep->lock, flags); /* We have to call this outside the lock */ if (pwake) @@ -714,9 +766,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) rb_insert_color(&epi->rbn, &ep->rbr); } -/* - * Must be called with "mtx" held. - */ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile, int fd) { @@ -737,8 +786,8 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, epi->ep = ep; ep_set_ffd(&epi->ffd, tfile, fd); epi->event = *event; + atomic_set(&epi->usecnt, 1); epi->nwait = 0; - epi->next = EP_UNACTIVE_PTR; /* Initialize the poll table using the queue callback */ epq.epi = epi; @@ -747,9 +796,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* * Attach the item to the poll hooks and get current event bits. * We can safely use the file* here because its usage count has - * been increased by the caller of this function. Note that after - * this operation completes, the poll callback can start hitting - * the new item. + * been increased by the caller of this function. */ revents = tfile->f_op->poll(tfile, &epq.pt); @@ -766,14 +813,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, list_add_tail(&epi->fllink, &tfile->f_ep_links); spin_unlock(&tfile->f_ep_lock); - /* - * Add the current item to the RB tree. All RB tree operations are - * protected by "mtx", and ep_insert() is called with "mtx" held. - */ - ep_rbtree_insert(ep, epi); - /* We have to drop the new item inside our item list to keep track of it */ - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); + + /* Add the current item to the rb-tree */ + ep_rbtree_insert(ep, epi); /* If the file is already "ready" we drop it inside the ready list */ if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) { @@ -786,7 +830,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, pwake++; } - spin_unlock_irqrestore(&ep->lock, flags); + write_unlock_irqrestore(&ep->lock, flags); /* We have to call this outside the lock */ if (pwake) @@ -802,14 +846,12 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* * We need to do this because an event could have been arrived on some - * allocated wait queue. Note that we don't care about the ep->ovflist - * list, since that is used/cleaned only inside a section bound by "mtx". - * And ep_insert() is called with "mtx" held. + * allocated wait queue. */ - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); if (ep_is_linked(&epi->rdllink)) list_del_init(&epi->rdllink); - spin_unlock_irqrestore(&ep->lock, flags); + write_unlock_irqrestore(&ep->lock, flags); kmem_cache_free(epi_cache, epi); error_return: @@ -818,7 +860,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* * Modify the interest event mask by dropping an event if the new mask - * has a match in the current file status. Must be called with "mtx" held. + * has a match in the current file status. */ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event) { @@ -840,28 +882,36 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even */ revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); /* Copy the data member from inside the lock */ epi->event.data = event->data; /* - * If the item is "hot" and it is not registered inside the ready - * list, push it inside. + * If the item is not linked to the RB tree it means that it's on its + * way toward the removal. Do nothing in this case. */ - if (revents & event->events) { - if (!ep_is_linked(&epi->rdllink)) { - list_add_tail(&epi->rdllink, &ep->rdllist); - - /* Notify waiting tasks that events are available */ - if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | - TASK_INTERRUPTIBLE); - if (waitqueue_active(&ep->poll_wait)) - pwake++; + if (ep_rb_linked(&epi->rbn)) { + /* + * If the item is "hot" and it is not registered inside the ready + * list, push it inside. If the item is not "hot" and it is currently + * registered inside the ready list, unlink it. + */ + if (revents & event->events) { + if (!ep_is_linked(&epi->rdllink)) { + list_add_tail(&epi->rdllink, &ep->rdllist); + + /* Notify waiting tasks that events are available */ + if (waitqueue_active(&ep->wq)) + __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | + TASK_INTERRUPTIBLE); + if (waitqueue_active(&ep->poll_wait)) + pwake++; + } } } - spin_unlock_irqrestore(&ep->lock, flags); + + write_unlock_irqrestore(&ep->lock, flags); /* We have to call this outside the lock */ if (pwake) @@ -870,50 +920,36 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even return 0; } -static int ep_send_events(struct eventpoll *ep, struct epoll_event __user *events, - int maxevents) +/* + * This function is called without holding the "ep->lock" since the call to + * __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ + * because of the way poll() is traditionally implemented in Linux. + */ +static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, + struct epoll_event __user *events, int maxevents) { int eventcnt, error = -EFAULT, pwake = 0; unsigned int revents; unsigned long flags; - struct epitem *epi, *nepi; - struct list_head txlist; - - INIT_LIST_HEAD(&txlist); - - /* - * We need to lock this because we could be hit by - * eventpoll_release_file() and epoll_ctl(EPOLL_CTL_DEL). - */ - mutex_lock(&ep->mtx); + struct epitem *epi; + struct list_head injlist; - /* - * Steal the ready list, and re-init the original one to the - * empty list. Also, set ep->ovflist to NULL so that events - * happening while looping w/out locks, are not lost. We cannot - * have the poll callback to queue directly on ep->rdllist, - * because we are doing it in the loop below, in a lockless way. - */ - spin_lock_irqsave(&ep->lock, flags); - list_splice(&ep->rdllist, &txlist); - INIT_LIST_HEAD(&ep->rdllist); - ep->ovflist = NULL; - spin_unlock_irqrestore(&ep->lock, flags); + INIT_LIST_HEAD(&injlist); /* * We can loop without lock because this is a task private list. * We just splice'd out the ep->rdllist in ep_collect_ready_items(). - * Items cannot vanish during the loop because we are holding "mtx". + * Items cannot vanish during the loop because we are holding "sem" in + * read. */ - for (eventcnt = 0; !list_empty(&txlist) && eventcnt < maxevents;) { - epi = list_first_entry(&txlist, struct epitem, rdllink); - - list_del_init(&epi->rdllink); + for (eventcnt = 0; !list_empty(txlist) && eventcnt < maxevents;) { + epi = list_first_entry(txlist, struct epitem, rdllink); + prefetch(epi->rdllink.next); /* * Get the ready file event set. We can safely use the file - * because we are holding the "mtx" and this will guarantee - * that both the file and the item will not vanish. + * because we are holding the "sem" in read and this will + * guarantee that both the file and the item will not vanish. */ revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); revents &= epi->event.events; @@ -921,8 +957,8 @@ static int ep_send_events(struct eventpoll *ep, struct epoll_event __user *event /* * Is the event mask intersect the caller-requested one, * deliver the event to userspace. Again, we are holding - * "mtx", so no operations coming from userspace can change - * the item. + * "sem" in read, so no operations coming from userspace + * can change the item. */ if (revents) { if (__put_user(revents, @@ -934,59 +970,59 @@ static int ep_send_events(struct eventpoll *ep, struct epoll_event __user *event epi->event.events &= EP_PRIVATE_BITS; eventcnt++; } + /* - * At this point, noone can insert into ep->rdllist besides - * us. The epoll_ctl() callers are locked out by us holding - * "mtx" and the poll callback will queue them in ep->ovflist. + * This is tricky. We are holding the "sem" in read, and this + * means that the operations that can change the "linked" status + * of the epoll item (epi->rbn and epi->rdllink), cannot touch + * them. Also, since we are "linked" from a epi->rdllink POV + * (the item is linked to our transmission list we just + * spliced), the ep_poll_callback() cannot touch us either, + * because of the check present in there. Another parallel + * epoll_wait() will not get the same result set, since we + * spliced the ready list before. Note that list_del() still + * shows the item as linked to the test in ep_poll_callback(). */ + list_del(&epi->rdllink); if (!(epi->event.events & EPOLLET) && - (revents & epi->event.events)) - list_add_tail(&epi->rdllink, &ep->rdllist); + (revents & epi->event.events)) + list_add_tail(&epi->rdllink, &injlist); + else { + /* + * Be sure the item is totally detached before re-init + * the list_head. After INIT_LIST_HEAD() is committed, + * the ep_poll_callback() can requeue the item again, + * but we don't care since we are already past it. + */ + smp_mb(); + INIT_LIST_HEAD(&epi->rdllink); + } } error = 0; -errxit: + errxit: - spin_lock_irqsave(&ep->lock, flags); /* - * During the time we spent in the loop above, some other events - * might have been queued by the poll callback. We re-insert them - * here (in case they are not already queued, or they're one-shot). + * If the re-injection list or the txlist are not empty, re-splice + * them to the ready list and do proper wakeups. */ - for (nepi = ep->ovflist; (epi = nepi) != NULL; - nepi = epi->next, epi->next = EP_UNACTIVE_PTR) { - if (!ep_is_linked(&epi->rdllink) && - (epi->event.events & ~EP_PRIVATE_BITS)) - list_add_tail(&epi->rdllink, &ep->rdllist); - } - /* - * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after - * releasing the lock, events will be queued in the normal way inside - * ep->rdllist. - */ - ep->ovflist = EP_UNACTIVE_PTR; - - /* - * In case of error in the event-send loop, or in case the number of - * ready events exceeds the userspace limit, we need to splice the - * "txlist" back inside ep->rdllist. - */ - list_splice(&txlist, &ep->rdllist); + if (!list_empty(&injlist) || !list_empty(txlist)) { + write_lock_irqsave(&ep->lock, flags); - if (!list_empty(&ep->rdllist)) { + list_splice(txlist, &ep->rdllist); + list_splice(&injlist, &ep->rdllist); /* - * Wake up (if active) both the eventpoll wait list and the ->poll() - * wait list (delayed after we release the lock). + * Wake up ( if active ) both the eventpoll wait list and the ->poll() + * wait list. */ if (waitqueue_active(&ep->wq)) __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE); if (waitqueue_active(&ep->poll_wait)) pwake++; - } - spin_unlock_irqrestore(&ep->lock, flags); - mutex_unlock(&ep->mtx); + write_unlock_irqrestore(&ep->lock, flags); + } /* We have to call this outside the lock */ if (pwake) @@ -995,6 +1031,41 @@ static int ep_send_events(struct eventpoll *ep, struct epoll_event __user *event return eventcnt == 0 ? error: eventcnt; } +/* + * Perform the transfer of events to user space. + */ +static int ep_events_transfer(struct eventpoll *ep, + struct epoll_event __user *events, int maxevents) +{ + int eventcnt; + unsigned long flags; + struct list_head txlist; + + INIT_LIST_HEAD(&txlist); + + /* + * We need to lock this because we could be hit by + * eventpoll_release_file() and epoll_ctl(EPOLL_CTL_DEL). + */ + down_read(&ep->sem); + + /* + * Steal the ready list, and re-init the original one to the + * empty list. + */ + write_lock_irqsave(&ep->lock, flags); + list_splice(&ep->rdllist, &txlist); + INIT_LIST_HEAD(&ep->rdllist); + write_unlock_irqrestore(&ep->lock, flags); + + /* Build result set in userspace */ + eventcnt = ep_send_events(ep, &txlist, events, maxevents); + + up_read(&ep->sem); + + return eventcnt; +} + static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout) { @@ -1012,7 +1083,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000; retry: - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); res = 0; if (list_empty(&ep->rdllist)) { @@ -1022,7 +1093,6 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, * ep_poll_callback() when events will become available. */ init_waitqueue_entry(&wait, current); - wait.flags |= WQ_FLAG_EXCLUSIVE; __add_wait_queue(&ep->wq, &wait); for (;;) { @@ -1039,9 +1109,9 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, break; } - spin_unlock_irqrestore(&ep->lock, flags); + write_unlock_irqrestore(&ep->lock, flags); jtimeout = schedule_timeout(jtimeout); - spin_lock_irqsave(&ep->lock, flags); + write_lock_irqsave(&ep->lock, flags); } __remove_wait_queue(&ep->wq, &wait); @@ -1051,7 +1121,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, /* Is it worth to try to dig for events ? */ eavail = !list_empty(&ep->rdllist); - spin_unlock_irqrestore(&ep->lock, flags); + write_unlock_irqrestore(&ep->lock, flags); /* * Try to transfer events to user space. In case we get 0 events and @@ -1059,17 +1129,18 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, * more luck. */ if (!res && eavail && - !(res = ep_send_events(ep, events, maxevents)) && jtimeout) + !(res = ep_events_transfer(ep, events, maxevents)) && jtimeout) goto retry; return res; } /* - * It opens an eventpoll file descriptor. The "size" parameter is there - * for historical reasons, when epoll was using an hash instead of an - * RB tree. With the current implementation, the "size" parameter is ignored - * (besides sanity checks). + * It opens an eventpoll file descriptor by suggesting a storage of "size" + * file descriptors. The size parameter is just an hint about how to size + * data structures. It won't prevent the user to store more than "size" + * file descriptors inside the epoll interface. It is the kernel part of + * the userspace epoll_create(2). */ asmlinkage long sys_epoll_create(int size) { @@ -1105,6 +1176,7 @@ asmlinkage long sys_epoll_create(int size) error_free: ep_free(ep); + kfree(ep); error_return: DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, error)); @@ -1114,7 +1186,8 @@ asmlinkage long sys_epoll_create(int size) /* * The following function implements the controller interface for * the eventpoll file that enables the insertion/removal/change of - * file descriptors inside the interest set. + * file descriptors inside the interest set. It represents + * the kernel part of the user space epoll_ctl(2). */ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event) @@ -1164,13 +1237,9 @@ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, */ ep = file->private_data; - mutex_lock(&ep->mtx); + down_write(&ep->sem); - /* - * Try to lookup the file inside our RB tree, Since we grabbed "mtx" - * above, we can be sure to be able to use the item looked up by - * ep_find() till we release the mutex. - */ + /* Try to lookup the file inside our RB tree */ epi = ep_find(ep, tfile, fd); error = -EINVAL; @@ -1197,7 +1266,13 @@ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, error = -ENOENT; break; } - mutex_unlock(&ep->mtx); + /* + * The function ep_find() increments the usage count of the structure + * so, if this is not NULL, we need to release it. + */ + if (epi) + ep_release_epitem(epi); + up_write(&ep->sem); error_tgt_fput: fput(tfile); @@ -1303,7 +1378,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, if (sigmask) { if (error == -EINTR) { memcpy(¤t->saved_sigmask, &sigsaved, - sizeof(sigsaved)); + sizeof(sigsaved)); set_thread_flag(TIF_RESTORE_SIGMASK); } else sigprocmask(SIG_SETMASK, &sigsaved, NULL); diff --git a/trunk/include/asm-alpha/mmu_context.h b/trunk/include/asm-alpha/mmu_context.h index 6a5be1f7debf..0bd7bd2ccb90 100644 --- a/trunk/include/asm-alpha/mmu_context.h +++ b/trunk/include/asm-alpha/mmu_context.h @@ -85,8 +85,8 @@ __reload_thread(struct pcb_struct *pcb) * +-------------+----------------+--------------+ */ -#include #ifdef CONFIG_SMP +#include #define cpu_last_asn(cpuid) (cpu_data[cpuid].last_asn) #else extern unsigned long last_asn; diff --git a/trunk/include/asm-h8300/atomic.h b/trunk/include/asm-h8300/atomic.h index b4cf0ea97ede..21f54428c86b 100644 --- a/trunk/include/asm-h8300/atomic.h +++ b/trunk/include/asm-h8300/atomic.h @@ -37,7 +37,6 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) } #define atomic_sub(i, v) atomic_sub_return(i, v) -#define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0) static __inline__ int atomic_inc_return(atomic_t *v) { diff --git a/trunk/include/asm-i386/kdebug.h b/trunk/include/asm-i386/kdebug.h index a185b5f73e7f..05c3117788b9 100644 --- a/trunk/include/asm-i386/kdebug.h +++ b/trunk/include/asm-i386/kdebug.h @@ -27,6 +27,7 @@ enum die_val { DIE_GPF, DIE_CALL, DIE_NMI_IPI, + DIE_NMI_POST, DIE_PAGE_FAULT, }; diff --git a/trunk/include/asm-i386/processor.h b/trunk/include/asm-i386/processor.h index 338668bfb0a2..70f3515c3db0 100644 --- a/trunk/include/asm-i386/processor.h +++ b/trunk/include/asm-i386/processor.h @@ -749,13 +749,9 @@ extern unsigned long boot_option_idle_override; extern void enable_sep_cpu(void); extern int sysenter_setup(void); -/* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; - extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); extern void cpu_init(void); -extern void init_gdt(int cpu); extern int force_mwait; diff --git a/trunk/include/asm-m68k/uaccess.h b/trunk/include/asm-m68k/uaccess.h index 5c1264cf0c65..6a4cf2081512 100644 --- a/trunk/include/asm-m68k/uaccess.h +++ b/trunk/include/asm-m68k/uaccess.h @@ -361,9 +361,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) long strncpy_from_user(char *dst, const char __user *src, long count); long strnlen_user(const char __user *src, long n); -unsigned long __clear_user(void __user *to, unsigned long n); - -#define clear_user __clear_user +unsigned long clear_user(void __user *to, unsigned long n); #define strlen_user(str) strnlen_user(str, 32767) diff --git a/trunk/include/asm-sparc/kdebug.h b/trunk/include/asm-sparc/kdebug.h index 631f15ffef73..404d80767323 100644 --- a/trunk/include/asm-sparc/kdebug.h +++ b/trunk/include/asm-sparc/kdebug.h @@ -58,10 +58,6 @@ static inline void sp_enter_debugger(void) sp_enter_debugger(); \ } while(0) -enum die_val { - DIE_UNUSED, -}; - #endif /* !(__ASSEMBLY__) */ /* Some nice offset defines for assembler code. */ @@ -70,4 +66,8 @@ enum die_val { #define KDEBUG_DUNNO2_OFF 0x8 #define KDEBUG_TEACH_OFF 0xc +enum die_val { + DIE_UNUSED, +}; + #endif /* !(_SPARC_KDEBUG_H) */ diff --git a/trunk/include/asm-sparc/system.h b/trunk/include/asm-sparc/system.h index 8b4e23b3bb38..8b6d9c9c8b93 100644 --- a/trunk/include/asm-sparc/system.h +++ b/trunk/include/asm-sparc/system.h @@ -11,7 +11,6 @@ #include #include #include -#include #ifndef __ASSEMBLY__ diff --git a/trunk/include/asm-sparc64/dma-mapping.h b/trunk/include/asm-sparc64/dma-mapping.h index 9329429fb7f6..2f858a2df94a 100644 --- a/trunk/include/asm-sparc64/dma-mapping.h +++ b/trunk/include/asm-sparc64/dma-mapping.h @@ -10,13 +10,10 @@ /* need struct page definitions */ #include -#include - static inline int dma_supported(struct device *dev, u64 mask) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_dma_supported(to_pci_dev(dev), mask); } @@ -24,8 +21,7 @@ dma_supported(struct device *dev, u64 mask) static inline int dma_set_mask(struct device *dev, u64 dma_mask) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_set_dma_mask(to_pci_dev(dev), dma_mask); } @@ -34,8 +30,7 @@ static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag); } @@ -44,8 +39,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); } @@ -54,8 +48,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); } @@ -64,8 +57,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); } @@ -75,8 +67,7 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); } @@ -85,8 +76,7 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); } @@ -95,8 +85,7 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); } @@ -105,8 +94,7 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); } @@ -115,8 +103,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, size, (int)direction); @@ -126,8 +113,7 @@ static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, size, (int)direction); @@ -137,8 +123,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction); } @@ -147,8 +132,7 @@ static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction); } diff --git a/trunk/include/asm-x86_64/kdebug.h b/trunk/include/asm-x86_64/kdebug.h index d7e2bcf49e4f..74feae945a26 100644 --- a/trunk/include/asm-x86_64/kdebug.h +++ b/trunk/include/asm-x86_64/kdebug.h @@ -22,6 +22,7 @@ enum die_val { DIE_GPF, DIE_CALL, DIE_NMI_IPI, + DIE_NMI_POST, DIE_PAGE_FAULT, }; diff --git a/trunk/include/linux/compat.h b/trunk/include/linux/compat.h index 0e69d2cf14aa..636502c02734 100644 --- a/trunk/include/linux/compat.h +++ b/trunk/include/linux/compat.h @@ -261,11 +261,5 @@ asmlinkage long compat_sys_epoll_pwait(int epfd, asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags); -asmlinkage long compat_sys_signalfd(int ufd, - const compat_sigset_t __user *sigmask, - compat_size_t sigsetsize); -asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags, - const struct compat_itimerspec __user *utmr); - #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/trunk/include/linux/init.h b/trunk/include/linux/init.h index e007ae4dc41e..8bc32bb2fce2 100644 --- a/trunk/include/linux/init.h +++ b/trunk/include/linux/init.h @@ -52,9 +52,14 @@ #endif /* For assembly routines */ +#ifdef CONFIG_HOTPLUG_CPU +#define __INIT .section ".text","ax" +#define __INITDATA .section ".data","aw" +#else #define __INIT .section ".init.text","ax" -#define __FINIT .previous #define __INITDATA .section ".init.data","aw" +#endif +#define __FINIT .previous #ifndef __ASSEMBLY__ /* diff --git a/trunk/include/linux/io.h b/trunk/include/linux/io.h index 8423dd376514..09d351236379 100644 --- a/trunk/include/linux/io.h +++ b/trunk/include/linux/io.h @@ -27,16 +27,8 @@ struct device; void __iowrite32_copy(void __iomem *to, const void *from, size_t count); void __iowrite64_copy(void __iomem *to, const void *from, size_t count); -#ifdef CONFIG_MMU int ioremap_page_range(unsigned long addr, unsigned long end, unsigned long phys_addr, pgprot_t prot); -#else -static inline int ioremap_page_range(unsigned long addr, unsigned long end, - unsigned long phys_addr, pgprot_t prot) -{ - return 0; -} -#endif /* * Managed iomap interface diff --git a/trunk/include/linux/major.h b/trunk/include/linux/major.h index 7e7c9093919a..0a74c52924c9 100644 --- a/trunk/include/linux/major.h +++ b/trunk/include/linux/major.h @@ -152,8 +152,6 @@ #define USB_ACM_AUX_MAJOR 167 #define USB_CHAR_MAJOR 180 -#define MMC_BLOCK_MAJOR 179 - #define VXVM_MAJOR 199 /* VERITAS volume i/o driver */ #define VXSPEC_MAJOR 200 /* VERITAS volume config driver */ #define VXDMP_MAJOR 201 /* VERITAS volume multipath driver */ diff --git a/trunk/include/linux/slub_def.h b/trunk/include/linux/slub_def.h index fd6627e2d115..ea27065e80e6 100644 --- a/trunk/include/linux/slub_def.h +++ b/trunk/include/linux/slub_def.h @@ -60,8 +60,7 @@ struct kmem_cache { #define KMALLOC_SHIFT_LOW 3 #ifdef CONFIG_LARGE_ALLOCS -#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT) =< 25 ? \ - (MAX_ORDER + PAGE_SHIFT - 1) : 25) +#define KMALLOC_SHIFT_HIGH 25 #else #if !defined(CONFIG_MMU) || NR_CPUS > 512 || MAX_NUMNODES > 256 #define KMALLOC_SHIFT_HIGH 20 @@ -88,9 +87,6 @@ static inline int kmalloc_index(int size) */ WARN_ON_ONCE(size == 0); - if (size >= (1 << KMALLOC_SHIFT_HIGH)) - return -1; - if (size > 64 && size <= 96) return 1; if (size > 128 && size <= 192) diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c index 51b6a6a6158c..3db5c3c460d7 100644 --- a/trunk/kernel/time/clocksource.c +++ b/trunk/kernel/time/clocksource.c @@ -74,7 +74,7 @@ static struct clocksource *watchdog; static struct timer_list watchdog_timer; static DEFINE_SPINLOCK(watchdog_lock); static cycle_t watchdog_last; -static unsigned long watchdog_resumed; +static int watchdog_resumed; /* * Interval: 0.5sec Threshold: 0.0625s @@ -104,7 +104,9 @@ static void clocksource_watchdog(unsigned long data) spin_lock(&watchdog_lock); - resumed = test_and_clear_bit(0, &watchdog_resumed); + resumed = watchdog_resumed; + if (unlikely(resumed)) + watchdog_resumed = 0; wdnow = watchdog->read(); wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask); @@ -149,7 +151,9 @@ static void clocksource_watchdog(unsigned long data) } static void clocksource_resume_watchdog(void) { - set_bit(0, &watchdog_resumed); + spin_lock(&watchdog_lock); + watchdog_resumed = 1; + spin_unlock(&watchdog_lock); } static void clocksource_check_watchdog(struct clocksource *cs) diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index 3d1042f82a68..f9217bf644f6 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -273,8 +273,6 @@ static int timekeeping_resume(struct sys_device *dev) unsigned long flags; unsigned long now = read_persistent_clock(); - clocksource_resume(); - write_seqlock_irqsave(&xtime_lock, flags); if (now && (now > timekeeping_suspend_time)) { diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 5ec5490f8d85..a6c580ac084b 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -1499,6 +1499,8 @@ unregister_time_interpolator(struct time_interpolator *ti) prev = &curr->next; } + clocksource_resume(); + write_seqlock_irqsave(&xtime_lock, flags); if (ti == time_interpolator) { /* we lost the best time-interpolator: */ diff --git a/trunk/net/ipv4/proc.c b/trunk/net/ipv4/proc.c index cdbc6c135849..37ab5802ca08 100644 --- a/trunk/net/ipv4/proc.c +++ b/trunk/net/ipv4/proc.c @@ -109,17 +109,6 @@ static const struct snmp_mib snmp4_ipstats_list[] = { SNMP_MIB_SENTINEL }; -/* Following RFC4293 items are displayed in /proc/net/netstat */ -static const struct snmp_mib snmp4_ipextstats_list[] = { - SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES), - SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS), - SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS), - SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), - SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS), - SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS), - SNMP_MIB_SENTINEL -}; - static const struct snmp_mib snmp4_icmp_list[] = { SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS), SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS), @@ -349,16 +338,6 @@ static int netstat_seq_show(struct seq_file *seq, void *v) snmp_fold_field((void **)net_statistics, snmp4_net_list[i].entry)); - seq_puts(seq, "\nIpExt:"); - for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) - seq_printf(seq, " %s", snmp4_ipextstats_list[i].name); - - seq_puts(seq, "\nIpExt:"); - for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) - seq_printf(seq, " %lu", - snmp_fold_field((void **)ip_statistics, - snmp4_ipextstats_list[i].entry)); - seq_putc(seq, '\n'); return 0; } diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index 30a5cb1b203e..be0ee8a34f9b 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb) IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = ipv6_hdr(skb); - deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || + deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); /* diff --git a/trunk/net/sched/sch_prio.c b/trunk/net/sched/sch_prio.c index 6d7542c26e47..269a6e17c6c4 100644 --- a/trunk/net/sched/sch_prio.c +++ b/trunk/net/sched/sch_prio.c @@ -75,7 +75,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) band = res.classid; } band = TC_H_MIN(band) - 1; - if (band >= q->bands) + if (band > q->bands) return q->queues[q->prio2band[0]]; return q->queues[band]; diff --git a/trunk/net/xfrm/xfrm_hash.c b/trunk/net/xfrm/xfrm_hash.c index 55ab5792af56..37643bb8768a 100644 --- a/trunk/net/xfrm/xfrm_hash.c +++ b/trunk/net/xfrm/xfrm_hash.c @@ -22,8 +22,7 @@ struct hlist_head *xfrm_hash_alloc(unsigned int sz) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) - __get_free_pages(GFP_KERNEL | __GFP_NOWARN, - get_order(sz)); + __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index d0882e53b6fc..95271e8426a1 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -796,10 +796,6 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, struct hlist_head *chain; struct hlist_node *entry; - *err = -ENOENT; - if (xfrm_policy_id2dir(id) != dir) - return NULL; - *err = 0; write_lock_bh(&xfrm_policy_lock); chain = xfrm_policy_byidx + idx_hash(id);