diff options
116 files changed, 1147 insertions, 807 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6e92ba6..9141193 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -79,6 +79,7 @@ parameter is applicable: Documentation/scsi/. SELINUX SELinux support is enabled. SERIAL Serial support is enabled. + SH SuperH architecture is enabled. SMP The kernel is an SMP kernel. SPARC Sparc architecture is enabled. SWSUSP Software suspend is enabled. @@ -485,7 +486,7 @@ and is between 256 and 4096 characters. It is defined in the file dtc3181e= [HW,SCSI] - earlyprintk= [IA-32,X86-64] + earlyprintk= [IA-32,X86-64,SH] earlyprintk=vga earlyprintk=serial[,ttySn[,baudrate]] @@ -1784,7 +1785,7 @@ and is between 256 and 4096 characters. It is defined in the file usbhid.mousepoll= [USBHID] The interval which mice are to be polled at. - vdso= [IA-32] + vdso= [IA-32,SH] vdso=1: enable VDSO (default) vdso=0: disable VDSO mapping diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index f9c99c9..1a3bdc2 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -45,11 +45,15 @@ special. Getting sparse ~~~~~~~~~~~~~~ -With git, you can just get it from +You can get latest released versions from the Sparse homepage at +http://www.kernel.org/pub/linux/kernel/people/josh/sparse/ - rsync://rsync.kernel.org/pub/scm/devel/sparse/sparse.git +Alternatively, you can get snapshots of the latest development version +of sparse using git to clone.. -and DaveJ has tar-balls at + git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git + +DaveJ has hourly generated tarballs of the git tree available at.. http://www.codemonkey.org.uk/projects/git-snapshots/sparse/ diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index f2e81cd..6f4388f 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -313,7 +313,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs) __mtdr(DBGREG_DC, dc); ti = current_thread_info(); - ti->flags |= _TIF_BREAKPOINT; + set_ti_thread_flag(ti, TIF_BREAKPOINT); /* The TLB miss handlers don't check thread flags */ if ((regs->pc >= (unsigned long)&itlb_miss) @@ -328,7 +328,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs) * single step. */ if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR) - ti->flags |= TIF_SINGLE_STEP; + set_ti_thread_flag(ti, TIF_SINGLE_STEP); } else { panic("Unable to handle debug trap at pc = %08lx\n", regs->pc); diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 7e803f4..adc01a1 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -49,39 +49,45 @@ out: return; } +static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) +{ + return (p > (unsigned long)tinfo) + && (p < (unsigned long)tinfo + THREAD_SIZE - 3); +} + #ifdef CONFIG_FRAME_POINTER static inline void __show_trace(struct task_struct *tsk, unsigned long *sp, struct pt_regs *regs) { - unsigned long __user *fp; - unsigned long __user *last_fp = NULL; - - if (regs) { - fp = (unsigned long __user *)regs->r7; - } else if (tsk == current) { - register unsigned long __user *real_fp __asm__("r7"); - fp = real_fp; - } else { - fp = (unsigned long __user *)tsk->thread.cpu_context.r7; - } + unsigned long lr, fp; + struct thread_info *tinfo; + + tinfo = (struct thread_info *) + ((unsigned long)sp & ~(THREAD_SIZE - 1)); + + if (regs) + fp = regs->r7; + else if (tsk == current) + asm("mov %0, r7" : "=r"(fp)); + else + fp = tsk->thread.cpu_context.r7; /* - * Walk the stack until (a) we get an exception, (b) the frame - * pointer becomes zero, or (c) the frame pointer gets stuck - * at the same value. + * Walk the stack as long as the frame pointer (a) is within + * the kernel stack of the task, and (b) it doesn't move + * downwards. */ - while (fp && fp != last_fp) { - unsigned long lr, new_fp = 0; - - last_fp = fp; - if (__get_user(lr, fp)) - break; - if (fp && __get_user(new_fp, fp + 1)) - break; - fp = (unsigned long __user *)new_fp; + while (valid_stack_ptr(tinfo, fp)) { + unsigned long new_fp; + lr = *(unsigned long *)fp; printk(" [<%08lx>] ", lr); print_symbol("%s\n", lr); + + new_fp = *(unsigned long *)(fp + 4); + if (new_fp <= fp) + break; + fp = new_fp; } printk("\n"); } diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index bc23550..472703f 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -752,7 +752,7 @@ static struct resource atmel_spi1_resource[] = { DEFINE_DEV(atmel_spi, 1); DEV_CLK(spi_clk, atmel_spi1, pba, 1); -static void +static void __init at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n, const u8 *pins) { diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c index fb13f72..8f7b1c3 100644 --- a/arch/avr32/mm/cache.c +++ b/arch/avr32/mm/cache.c @@ -121,9 +121,8 @@ void flush_icache_range(unsigned long start, unsigned long end) void flush_icache_page(struct vm_area_struct *vma, struct page *page) { if (vma->vm_flags & VM_EXEC) { - void *v = kmap(page); + void *v = page_address(page); __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE); - kunmap(v); } } diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index bf86f76..a7d22d9 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c @@ -14,11 +14,8 @@ #ifdef CONFIG_ACPI -static int nvidia_hpet_detected __initdata; - static int __init nvidia_hpet_check(struct acpi_table_header *header) { - nvidia_hpet_detected = 1; return 0; } #endif @@ -29,9 +26,7 @@ static int __init check_bridge(int vendor, int device) /* According to Nvidia all timer overrides are bogus unless HPET is enabled. */ if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { - nvidia_hpet_detected = 0; - acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check); - if (nvidia_hpet_detected == 0) { + if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { acpi_skip_timer_override = 1; printk(KERN_INFO "Nvidia board " "detected. Ignoring ACPI " diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 9b0dd27..4ff55e6 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -45,6 +45,7 @@ #include <linux/notifier.h> #include <linux/cpu.h> #include <linux/percpu.h> +#include <linux/nmi.h> #include <linux/delay.h> #include <linux/mc146818rtc.h> @@ -1278,8 +1279,9 @@ void __cpu_die(unsigned int cpu) int __cpuinit __cpu_up(unsigned int cpu) { + unsigned long flags; #ifdef CONFIG_HOTPLUG_CPU - int ret=0; + int ret = 0; /* * We do warm boot only on cpus that had booted earlier @@ -1297,23 +1299,25 @@ int __cpuinit __cpu_up(unsigned int cpu) /* In case one didn't come up */ if (!cpu_isset(cpu, cpu_callin_map)) { printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); - local_irq_enable(); return -EIO; } - local_irq_enable(); - per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; /* Unleash the CPU! */ cpu_set(cpu, smp_commenced_mask); /* - * Check TSC synchronization with the AP: + * Check TSC synchronization with the AP (keep irqs disabled + * while doing so): */ + local_irq_save(flags); check_tsc_sync_source(cpu); + local_irq_restore(flags); - while (!cpu_isset(cpu, cpu_online_map)) + while (!cpu_isset(cpu, cpu_online_map)) { cpu_relax(); + touch_nmi_watchdog(); + } #ifdef CONFIG_X86_GENERICARCH if (num_online_cpus() > 8 && genapic == &apic_default) diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 75a2a2c..2236fab 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -35,6 +35,7 @@ void foo(void) BLANK(); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); BLANK(); diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 4061593..49b9368 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -971,6 +971,11 @@ efi_memmap_init(unsigned long *s, unsigned long *e) if (!is_memory_available(md)) continue; +#ifdef CONFIG_CRASH_DUMP + /* saved_max_pfn should ignore max_addr= command line arg */ + if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT)) + saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT); +#endif /* * Round ends inward to granule boundaries * Give trimmings to uncached allocator @@ -1010,11 +1015,6 @@ efi_memmap_init(unsigned long *s, unsigned long *e) } else ae = efi_md_end(md); -#ifdef CONFIG_CRASH_DUMP - /* saved_max_pfn should ignore max_addr= command line arg */ - if (saved_max_pfn < (ae >> PAGE_SHIFT)) - saved_max_pfn = (ae >> PAGE_SHIFT); -#endif /* keep within max_addr= and min_addr= command line arg */ as = max(as, min_addr); ae = min(ae, max_addr); diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 7a05b1c..8589e84 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -10,6 +10,8 @@ * probably broke it along the way... ;-) * 13-Jul-04 clameter Implement fsys_clock_gettime and revise fsys_gettimeofday to make * it capable of using memory based clocks without falling back to C code. + * 08-Feb-07 Fenghua Yu Implement fsys_getcpu. + * */ #include <asm/asmmacro.h> @@ -505,6 +507,59 @@ EX(.fail_efault, (p15) st8 [r34]=r3) #endif END(fsys_rt_sigprocmask) +/* + * fsys_getcpu doesn't use the third parameter in this implementation. It reads + * current_thread_info()->cpu and corresponding node in cpu_to_node_map. + */ +ENTRY(fsys_getcpu) + .prologue + .altrp b6 + .body + ;; + add r2=TI_FLAGS+IA64_TASK_SIZE,r16 + tnat.nz p6,p0 = r32 // guard against NaT argument + add r3=TI_CPU+IA64_TASK_SIZE,r16 + ;; + ld4 r3=[r3] // M r3 = thread_info->cpu + ld4 r2=[r2] // M r2 = thread_info->flags +(p6) br.cond.spnt.few .fail_einval // B + ;; + tnat.nz p7,p0 = r33 // I guard against NaT argument +(p7) br.cond.spnt.few .fail_einval // B +#ifdef CONFIG_NUMA + movl r17=cpu_to_node_map + ;; +EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles +EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles + shladd r18=r3,1,r17 + ;; + ld2 r20=[r18] // r20 = cpu_to_node_map[cpu] + and r2 = TIF_ALLWORK_MASK,r2 + ;; + cmp.ne p8,p0=0,r2 +(p8) br.spnt.many fsys_fallback_syscall + ;; + ;; +EX(.fail_efault, st4 [r32] = r3) +EX(.fail_efault, st2 [r33] = r20) + mov r8=0 + ;; +#else +EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles +EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles + and r2 = TIF_ALLWORK_MASK,r2 + ;; + cmp.ne p8,p0=0,r2 +(p8) br.spnt.many fsys_fallback_syscall + ;; +EX(.fail_efault, st4 [r32] = r3) +EX(.fail_efault, st2 [r33] = r0) + mov r8=0 + ;; +#endif + FSYS_RETURN +END(fsys_getcpu) + ENTRY(fsys_fallback_syscall) .prologue .altrp b6 @@ -878,6 +933,56 @@ fsyscall_table: data8 0 // timer_delete data8 0 // clock_settime data8 fsys_clock_gettime // clock_gettime + data8 0 // clock_getres // 1255 + data8 0 // clock_nanosleep + data8 0 // fstatfs64 + data8 0 // statfs64 + data8 0 // mbind + data8 0 // get_mempolicy // 1260 + data8 0 // set_mempolicy + data8 0 // mq_open + data8 0 // mq_unlink + data8 0 // mq_timedsend + data8 0 // mq_timedreceive // 1265 + data8 0 // mq_notify + data8 0 // mq_getsetattr + data8 0 // kexec_load + data8 0 // vserver + data8 0 // waitid // 1270 + data8 0 // add_key + data8 0 // request_key + data8 0 // keyctl + data8 0 // ioprio_set + data8 0 // ioprio_get // 1275 + data8 0 // move_pages + data8 0 // inotify_init + data8 0 // inotify_add_watch + data8 0 // inotify_rm_watch + data8 0 // migrate_pages // 1280 + data8 0 // openat + data8 0 // mkdirat + data8 0 // mknodat + data8 0 // fchownat + data8 0 // futimesat // 1285 + data8 0 // newfstatat + data8 0 // unlinkat + data8 0 // renameat + data8 0 // linkat + data8 0 // symlinkat // 1290 + data8 0 // readlinkat + data8 0 // fchmodat + data8 0 // faccessat + data8 0 + data8 0 // 1295 + data8 0 // unshare + data8 0 // splice + data8 0 // set_robust_list + data8 0 // get_robust_list + data8 0 // sync_file_range // 1300 + data8 0 // tee + data8 0 // vmsplice + data8 0 + data8 fsys_getcpu // getcpu // 1304 // fill in zeros for the remaining entries .zero: diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index d6aab40..dcfbf3e 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -446,7 +446,7 @@ iosapic_end_level_irq (unsigned int irq) #define iosapic_disable_level_irq mask_irq #define iosapic_ack_level_irq nop -struct hw_interrupt_type irq_type_iosapic_level = { +struct irq_chip irq_type_iosapic_level = { .name = "IO-SAPIC-level", .startup = iosapic_startup_level_irq, .shutdown = iosapic_shutdown_level_irq, @@ -454,6 +454,8 @@ struct hw_interrupt_type irq_type_iosapic_level = { .disable = iosapic_disable_level_irq, .ack = iosapic_ack_level_irq, .end = iosapic_end_level_irq, + .mask = mask_irq, + .unmask = unmask_irq, .set_affinity = iosapic_set_affinity }; @@ -493,7 +495,7 @@ iosapic_ack_edge_irq (unsigned int irq) #define iosapic_disable_edge_irq nop #define iosapic_end_edge_irq nop -struct hw_interrupt_type irq_type_iosapic_edge = { +struct irq_chip irq_type_iosapic_edge = { .name = "IO-SAPIC-edge", .startup = iosapic_startup_edge_irq, .shutdown = iosapic_disable_edge_irq, @@ -501,6 +503,8 @@ struct hw_interrupt_type irq_type_iosapic_edge = { .disable = iosapic_disable_edge_irq, .ack = iosapic_ack_edge_irq, .end = iosapic_end_edge_irq, + .mask = mask_irq, + .unmask = unmask_irq, .set_affinity = iosapic_set_affinity }; diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 7d6fe65..339e8a5 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -91,8 +91,6 @@ static struct resource code_resource = { .name = "Kernel code", .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; -extern void efi_initialize_iomem_resources(struct resource *, - struct resource *); extern char _text[], _end[], _etext[]; unsigned long ia64_max_cacheline_size; diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 8c5bee0..8d2a1bf 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -205,7 +205,17 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) (void)sn_retarget_vector(sn_irq_info, nasid, slice); } -struct hw_interrupt_type irq_type_sn = { +static void +sn_mask_irq(unsigned int irq) +{ +} + +static void +sn_unmask_irq(unsigned int irq) +{ +} + +struct irq_chip irq_type_sn = { .name = "SN hub", .startup = sn_startup_irq, .shutdown = sn_shutdown_irq, @@ -213,6 +223,8 @@ struct hw_interrupt_type irq_type_sn = { .disable = sn_disable_irq, .ack = sn_ack_irq, .end = sn_end_irq, + .mask = sn_mask_irq, + .unmask = sn_unmask_irq, .set_affinity = sn_set_affinity_irq }; diff --git a/arch/mips/arc/init.c b/arch/mips/arc/init.c index 0ac8f42..e2f75b1 100644 --- a/arch/mips/arc/init.c +++ b/arch/mips/arc/init.c @@ -23,16 +23,16 @@ LONG *_prom_argv, *_prom_envp; void __init prom_init(void) { PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK; + romvec = ROMVECTOR; - ULONG cnt; - CHAR c; prom_argc = fw_arg0; _prom_argv = (LONG *) fw_arg1; _prom_envp = (LONG *) fw_arg2; if (pb->magic != 0x53435241) { - printk(KERN_CRIT "Aieee, bad prom vector magic %08lx\n", pb->magic); + printk(KERN_CRIT "Aieee, bad prom vector magic %08lx\n", + (unsigned long) pb->magic); while(1) ; } diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 30d433f..1df544c 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -564,49 +564,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs) return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } - -/* - * Implement the event wait interface for the eventpoll file. It is the kernel - * part of the user space epoll_pwait(2). - */ -asmlinkage long compat_sys_epoll_pwait(int epfd, - struct epoll_event __user *events, int maxevents, int timeout, - const compat_sigset_t __user *sigmask, size_t sigsetsize) -{ - int error; - sigset_t ksigmask, sigsaved; - - /* - * If the caller wants a certain signal mask to be set during the wait, - * we apply it here. - */ - if (sigmask) { - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask))) - return -EFAULT; - if (__copy_conv_sigset_from_user(&ksigmask, sigmask)) - return -EFAULT; - sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); - sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); - } - - error = sys_epoll_wait(epfd, events, maxevents, timeout); - - /* - * If we changed the signal mask, we need to restore the original one. - * In case we've got a signal while waiting, we do not restore the - * signal mask yet, and we allow do_signal() to deliver the signal on - * the way back to userspace, before the signal mask is restored. - */ - if (sigmask) { - if (error == -EINTR) { - memcpy(¤t->saved_sigmask, &sigsaved, - sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); - } else - sigprocmask(SIG_SETMASK, &sigsaved, NULL); - } - - return error; -} diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile index 3c93012..ed5f5a9 100644 --- a/arch/sh/boards/renesas/r7780rp/Makefile +++ b/arch/sh/boards/renesas/r7780rp/Makefile @@ -2,6 +2,6 @@ # Makefile for the R7780RP-1 specific parts of the kernel # -obj-y := setup.o io.o irq.o +obj-y := setup.o irq.o obj-$(CONFIG_PUSH_SWITCH) += psw.o diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c deleted file mode 100644 index f74d2ff..0000000 --- a/arch/sh/boards/renesas/r7780rp/io.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2001 Ian da Silva, Jeremy Siegel - * Based largely on io_se.c. - * - * I/O routine for Renesas Solutions Highlander R7780RP-1 - * - * Initial version only to support LAN access; some - * placeholder code from io_r7780rp.c left in with the - * expectation of later SuperIO and PCMCIA access. - */ -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/io.h> -#include <asm/r7780rp.h> -#include <asm/addrspace.h> - -static inline unsigned long port88796l(unsigned int port, int flag) -{ - unsigned long addr; - - if (flag) - addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1); - else - addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000; - - return addr; -} - -#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE) -#define CHECK_AX88796L_PORT(port) \ - ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20))) -#else -#define CHECK_AX88796L_PORT(port) (0) -#endif - -/* - * General outline: remap really low stuff [eventually] to SuperIO, - * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) - * is mapped through the PCI IO window. Stuff with high bits (PXSEG) - * should be way beyond the window, and is used w/o translation for - * compatibility. - */ -u8 r7780rp_inb(unsigned long port) -{ - if (CHECK_AX88796L_PORT(port)) - return ctrl_inw(port88796l(port, 0)) & 0xff; - else if (is_pci_ioaddr(port)) - return ctrl_inb(pci_ioaddr(port)); - - return ctrl_inw(port) & 0xff; -} - -u8 r7780rp_inb_p(unsigned long port) -{ - u8 v; - - if (CHECK_AX88796L_PORT(port)) - v = ctrl_inw(port88796l(port, 0)) & 0xff; - else if (is_pci_ioaddr(port)) - v = ctrl_inb(pci_ioaddr(port)); - else - v = ctrl_inw(port) & 0xff; - - ctrl_delay(); - - return v; -} - -u16 r7780rp_inw(unsigned long port) -{ - if (is_pci_ioaddr(port)) - return ctrl_inw(pci_ioaddr(port)); - - return ctrl_inw(port); -} - -u32 r7780rp_inl(unsigned long port) -{ - if (is_pci_ioaddr(port)) - return ctrl_inl(pci_ioaddr(port)); - - return ctrl_inl(port); -} - -void r7780rp_outb(u8 value, unsigned long port) -{ - if (CHECK_AX88796L_PORT(port)) - ctrl_outw(value, port88796l(port, 0)); - else if (is_pci_ioaddr(port)) - ctrl_outb(value, pci_ioaddr(port)); - else - ctrl_outb(value, port); -} - -void r7780rp_outb_p(u8 value, unsigned long port) -{ - if (CHECK_AX88796L_PORT(port)) - ctrl_outw(value, port88796l(port, 0)); - else if (is_pci_ioaddr(port)) - ctrl_outb(value, pci_ioaddr(port)); - else - ctrl_outb(value, port); - - ctrl_delay(); -} - -void r7780rp_outw(u16 value, unsigned long port) -{ - if (is_pci_ioaddr(port)) - ctrl_outw(value, pci_ioaddr(port)); - else - ctrl_outw(value, port); -} - -void r7780rp_outl(u32 value, unsigned long port) -{ - if (is_pci_ioaddr(port)) - ctrl_outl(value, pci_ioaddr(port)); - else - ctrl_outl(value, port); -} - -void r7780rp_insb(unsigned long port, void *dst, unsigned long count) -{ - volatile u16 *p; - u8 *buf = dst; - - if (CHECK_AX88796L_PORT(port)) { - p = (volatile u16 *)port88796l(port, 0); - while (count--) - *buf++ = *p & 0xff; - } else if (is_pci_ioaddr(port)) { - volatile u8 *bp = (volatile u8 *)pci_ioaddr(port); - - while (count--) - *buf++ = *bp; - } else { - p = (volatile u16 *)port; - while (count--) - *buf++ = *p & 0xff; - } -} - -void r7780rp_insw(unsigned long port, void *dst, unsigned long count) -{ - volatile u16 *p; - u16 *buf = dst; - - if (CHECK_AX88796L_PORT(port)) - p = (volatile u16 *)port88796l(port, 1); - else if (is_pci_ioaddr(port)) - p = (volatile u16 *)pci_ioaddr(port); - else - p = (volatile u16 *)port; - - while (count--) - *buf++ = *p; - - flush_dcache_all(); -} - -void r7780rp_insl(unsigned long port, void *dst, unsigned long count) -{ - if (is_pci_ioaddr(port)) { - volatile u32 *p = (volatile u32 *)pci_ioaddr(port); - u32 *buf = dst; - - while (count--) - *buf++ = *p; - } -} - -void r7780rp_outsb(unsigned long port, const void *src, unsigned long count) -{ - volatile u16 *p; - const u8 *buf = src; - - if (CHECK_AX88796L_PORT(port)) { - p = (volatile u16 *)port88796l(port, 0); - while (count--) - *p = *buf++; - } else if (is_pci_ioaddr(port)) { - volatile u8 *bp = (volatile u8 *)pci_ioaddr(port); - - while (count--) - *bp = *buf++; - } else - while (count--) - ctrl_outb(*buf++, port); -} - -void r7780rp_outsw(unsigned long port, const void *src, unsigned long count) -{ - volatile u16 *p; - const u16 *buf = src; - - if (CHECK_AX88796L_PORT(port)) - p = (volatile u16 *)port88796l(port, 1); - else if (is_pci_ioaddr(port)) - p = (volatile u16 *)pci_ioaddr(port); - else - p = (volatile u16 *)port; - - while (count--) - *p = *buf++; - - flush_dcache_all(); -} - -void r7780rp_outsl(unsigned long port, const void *src, unsigned long count) -{ - const u32 *buf = src; - u32 *p; - - if (is_pci_ioaddr(port)) - p = (u32 *)pci_ioaddr(port); - else - p = (u32 *)port; - - while (count--) - ctrl_outl(*buf++, (unsigned long)p); -} - -void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size) -{ - if (CHECK_AX88796L_PORT(port)) - return (void __iomem *)port88796l(port, size > 1); - else if (is_pci_ioaddr(port)) - return (void __iomem *)pci_ioaddr(port); - - return (void __iomem *)port; -} diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index 0d74db9..2faba66 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -187,31 +187,7 @@ static void __init r7780rp_setup(char **cmdline_p) struct sh_machine_vector mv_r7780rp __initmv = { .mv_name = "Highlander R7780RP-1", .mv_setup = r7780rp_setup, - .mv_nr_irqs = 109, - - .mv_inb = r7780rp_inb, - .mv_inw = r7780rp_inw, - .mv_inl = r7780rp_inl, - .mv_outb = r7780rp_outb, - .mv_outw = r7780rp_outw, - .mv_outl = r7780rp_outl, - - .mv_inb_p = r7780rp_inb_p, - .mv_inw_p = r7780rp_inw, - .mv_inl_p = r7780rp_inl, - .mv_outb_p = r7780rp_outb_p, - .mv_outw_p = r7780rp_outw, - .mv_outl_p = r7780rp_outl, - - .mv_insb = r7780rp_insb, - .mv_insw = r7780rp_insw, - .mv_insl = r7780rp_insl, - .mv_outsb = r7780rp_outsb, - .mv_outsw = r7780rp_outsw, - .mv_outsl = r7780rp_outsl, - - .mv_ioport_map = r7780rp_ioport_map, .mv_init_irq = init_r7780rp_IRQ, }; ALIAS_MV(r7780rp) diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index 44b4208..593f26a 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -12,6 +12,7 @@ #include <linux/platform_device.h> #include <linux/pata_platform.h> #include <linux/serial_8250.h> +#include <linux/sm501.h> #include <linux/pm.h> #include <asm/machvec.h> #include <asm/rts7751r2d.h> @@ -111,10 +112,35 @@ static struct platform_device heartbeat_device = { .resource = heartbeat_resources, }; +static struct resource sm501_resources[] = { + [0] = { + .start = 0x10000000, + .end = 0x13e00000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0x13e00000, + .end = 0x13ffffff, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = 32, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sm501_device = { + .name = "sm501", + .id = -1, + .num_resources = ARRAY_SIZE(sm501_resources), + .resource = sm501_resources, +}; + static struct platform_device *rts7751r2d_devices[] __initdata = { &uart_device, &heartbeat_device, &cf_ide_device, + &sm501_device, }; static int __init rts7751r2d_devices_setup(void) diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig index db6a02d..a59bb78 100644 --- a/arch/sh/configs/rts7751r2d_defconfig +++ b/arch/sh/configs/rts7751r2d_defconfig @@ -1,14 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Thu Feb 15 17:17:29 2007 +# Linux kernel version: 2.6.21-rc1 +# Thu Mar 1 16:42:40 2007 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_GENERIC_TIME is not set @@ -33,6 +32,7 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set @@ -119,7 +119,6 @@ CONFIG_SH_RTS7751R2D=y # CONFIG_SH_SHMIN is not set # CONFIG_SH_7206_SOLUTION_ENGINE is not set # CONFIG_SH_7619_SOLUTION_ENGINE is not set -# CONFIG_SH_ASDAP310 is not set # CONFIG_SH_UNKNOWN is not set # @@ -281,7 +280,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00010000 CONFIG_BOOT_LINK_OFFSET=0x00800000 # CONFIG_UBC_WAKEUP is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" +CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1" # # Bus options @@ -433,6 +432,7 @@ CONFIG_FW_LOADER=m # # Plug and Play support # +# CONFIG_PNPACPI is not set # # Block devices @@ -770,7 +770,26 @@ CONFIG_NET_WIRELESS=y # # Input device support # -# CONFIG_INPUT is not set +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Hardware I/O ports @@ -781,7 +800,10 @@ CONFIG_NET_WIRELESS=y # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -857,6 +879,11 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # +# Multifunction device drivers +# +CONFIG_MFD_SM501=y + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -869,9 +896,66 @@ CONFIG_HWMON=y # # Graphics support # -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frambuffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_EPSON1355 is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +CONFIG_FB_SM501=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +# CONFIG_LOGO_SUPERH_MONO is not set +# CONFIG_LOGO_SUPERH_VGA16 is not set +CONFIG_LOGO_SUPERH_CLUT224=y # # Sound @@ -985,6 +1069,12 @@ CONFIG_SOUND_PRIME=m CONFIG_AC97_BUS=m # +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# # USB support # CONFIG_USB_ARCH_HAS_HCD=y @@ -1237,7 +1327,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_EARLY_SCIF_CONSOLE=y CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000 CONFIG_EARLY_PRINTK=y -# CONFIG_KGDB is not set +# CONFIG_SH_KGDB is not set # # Security options diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index ab4ebb8..b467280 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -224,7 +224,7 @@ work_resched: syscall_exit_work: ! r0: current_thread_info->flags ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE, r0 + tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 66626c0..771ea42 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/io.h> #include <asm/machvec.h> -#include <asm/cacheflush.h> #ifdef CONFIG_CPU_SH3 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a @@ -96,7 +95,6 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) while (count--) *buf++ = *port_addr; - flush_dcache_all(); dummy_read(); } @@ -171,7 +169,6 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) while (count--) *port_addr = *buf++; - flush_dcache_all(); dummy_read(); } diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 9d6a438..e760736 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -250,12 +250,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->regs[15] = usp; ti->addr_limit = USER_DS; } else { - childregs->regs[15] = (unsigned long)task_stack_page(p) + - THREAD_SIZE; + childregs->regs[15] = (unsigned long)childregs; ti->addr_limit = KERNEL_DS; } - if (clone_flags & CLONE_SETTLS) + if (clone_flags & CLONE_SETTLS) childregs->gbr = childregs->regs[0]; childregs->regs[0] = 0; /* Set return value for child */ diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 04ca13a..855f724 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -8,7 +8,6 @@ * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka * */ - #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> @@ -20,8 +19,7 @@ #include <linux/slab.h> #include <linux/security.h> #include <linux/signal.h> - -#include <asm/io.h> +#include <linux/io.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/system.h> @@ -59,6 +57,23 @@ static inline int put_stack_long(struct task_struct *task, int offset, return 0; } +static void ptrace_disable_singlestep(struct task_struct *child) +{ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); + + /* + * Ensure the UBC is not programmed at the next context switch. + * + * Normally this is not needed but there are sequences such as + * singlestep, signal delivery, and continue that leave the + * ubc_pc non-zero leading to spurious SIGTRAPs. + */ + if (child->thread.ubc_pc != 0) { + ubc_usercnt -= 1; + child->thread.ubc_pc = 0; + } +} + /* * Called by kernel/ptrace.c when detaching.. * @@ -66,7 +81,7 @@ static inline int put_stack_long(struct task_struct *task, int offset, */ void ptrace_disable(struct task_struct *child) { - /* nothing to do.. */ + ptrace_disable_singlestep(child); } long arch_ptrace(struct task_struct *child, long request, long addr, long data) @@ -76,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; int copied; @@ -94,7 +109,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) unsigned long tmp; ret = -EIO; - if ((addr & 3) || addr < 0 || + if ((addr & 3) || addr < 0 || addr > sizeof(struct user) - 3) break; @@ -129,7 +144,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0 || + if ((addr & 3) || addr < 0 || addr > sizeof(struct user) - 3) break; @@ -156,6 +171,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + + ptrace_disable_singlestep(child); + child->exit_code = data; wake_up_process(child); ret = 0; @@ -163,14 +181,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { ret = 0; if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; + ptrace_disable_singlestep(child); child->exit_code = SIGKILL; wake_up_process(child); break; @@ -196,6 +215,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ubc_usercnt += 1; child->thread.ubc_pc = pc; + set_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -248,14 +268,15 @@ asmlinkage void do_syscall_trace(void) { struct task_struct *tsk = current; - if (!test_thread_flag(TIF_SYSCALL_TRACE)) + if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SINGLESTEP)) return; if (!(tsk->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && + !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 32f10a0..9f39ef1 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -589,6 +589,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } + + return; } no_signal: @@ -598,7 +600,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) if (regs->regs[0] == -ERESTARTNOHAND || regs->regs[0] == -ERESTARTSYS || regs->regs[0] == -ERESTARTNOINTR) { - regs->regs[0] = save_r0; + regs->regs[0] = save_r0; regs->pc -= 2; } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { regs->pc -= 2; diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 75de165..78a6c09 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -3,6 +3,7 @@ * Written by Niibe Yutaka */ #include <asm/thread_info.h> +#include <asm/cache.h> #include <asm-generic/vmlinux.lds.h> #ifdef CONFIG_CPU_LITTLE_ENDIAN @@ -53,7 +54,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); .data.page_aligned : { *(.data.page_aligned) } - . = ALIGN(32); + . = ALIGN(L1_CACHE_BYTES); __per_cpu_start = .; .data.percpu : { *(.data.percpu) } __per_cpu_end = .; diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index e0cd4b7..981b040 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -237,20 +237,10 @@ static inline void flush_cache_4096(unsigned long start, /* * Write back & invalidate the D-cache of the page. * (To avoid "alias" issues) - * - * This uses a lazy write-back on UP, which is explicitly - * disabled on SMP. */ void flush_dcache_page(struct page *page) { -#ifndef CONFIG_SMP - struct address_space *mapping = page_mapping(page); - - if (mapping && !mapping_mapped(mapping)) - set_bit(PG_dcache_dirty, &page->flags); - else -#endif - { + if (test_bit(PG_mapped, &page->flags)) { unsigned long phys = PHYSADDR(page_address(page)); unsigned long addr = CACHE_OC_ADDRESS_ARRAY; int i, n; diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index 31f8deb..4896d73 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c @@ -3,11 +3,11 @@ * * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2004 Alex Song - * Copyright (C) 2006 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. + * */ #include <linux/init.h> #include <linux/mman.h> @@ -51,6 +51,7 @@ static inline void cache_wback_all(void) if ((data & v) == v) ctrl_outl(data & ~v, addr); + } addrstart += current_cpu_data.dcache.way_incr; @@ -127,11 +128,7 @@ static void __flush_dcache_page(unsigned long phys) */ void flush_dcache_page(struct page *page) { - struct address_space *mapping = page_mapping(page); - - if (mapping && !mapping_mapped(mapping)) - set_bit(PG_dcache_dirty, &page->flags); - else + if (test_bit(PG_mapped, &page->flags)) __flush_dcache_page(PHYSADDR(page_address(page))); } diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 969efece..df69da9 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -23,6 +23,7 @@ extern struct mutex p3map_mutex[]; */ void clear_user_page(void *to, unsigned long address, struct page *page) { + __set_bit(PG_mapped, &page->flags); if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) clear_page(to); else { @@ -58,6 +59,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page) void copy_user_page(void *to, void *from, unsigned long address, struct page *page) { + __set_bit(PG_mapped, &page->flags); if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) copy_page(to, from); else { @@ -82,3 +84,23 @@ void copy_user_page(void *to, void *from, unsigned long address, mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } + +/* + * For SH-4, we have our own implementation for ptep_get_and_clear + */ +inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + pte_t pte = *ptep; + + pte_clear(mm, addr, ptep); + if (!pte_not_present(pte)) { + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + struct address_space *mapping = page_mapping(page); + if (!mapping || !mapping_writably_mapped(mapping)) + __clear_bit(PG_mapped, &page->flags); + } + } + return pte; +} diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c index 887ab9d..a4b015f 100644 --- a/arch/sh/mm/pg-sh7705.c +++ b/arch/sh/mm/pg-sh7705.c @@ -7,7 +7,9 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. + * */ + #include <linux/init.h> #include <linux/mman.h> #include <linux/mm.h> @@ -74,6 +76,7 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) { struct page *page = virt_to_page(to); + __set_bit(PG_mapped, &page->flags); if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { clear_page(to); __flush_wback_region(to, PAGE_SIZE); @@ -92,11 +95,12 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) * @from: P1 address * @address: U0 address to be mapped */ -void copy_user_page(void *to, void *from, unsigned long address, - struct page *pg) +void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) { struct page *page = virt_to_page(to); + + __set_bit(PG_mapped, &page->flags); if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { copy_page(to, from); __flush_wback_region(to, PAGE_SIZE); @@ -108,3 +112,26 @@ void copy_user_page(void *to, void *from, unsigned long address, __flush_wback_region(to, PAGE_SIZE); } } + +/* + * For SH7705, we have our own implementation for ptep_get_and_clear + * Copied from pg-sh4.c + */ +inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + pte_t pte = *ptep; + + pte_clear(mm, addr, ptep); + if (!pte_not_present(pte)) { + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + struct address_space *mapping = page_mapping(page); + if (!mapping || !mapping_writably_mapped(mapping)) + __clear_bit(PG_mapped, &page->flags); + } + } + + return pte; +} + diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c index d2f7b4a..6f45c1f 100644 --- a/arch/sh/mm/tlb-flush.c +++ b/arch/sh/mm/tlb-flush.c @@ -2,17 +2,15 @@ * TLB flushing operations for SH with an MMU. * * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 - 2006 Paul Mundt + * Copyright (C) 2003 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ #include <linux/mm.h> -#include <linux/io.h> #include <asm/mmu_context.h> #include <asm/tlbflush.h> -#include <asm/cacheflush.h> void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { @@ -140,54 +138,3 @@ void local_flush_tlb_all(void) ctrl_barrier(); local_irq_restore(flags); } - -void update_mmu_cache(struct vm_area_struct *vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - unsigned long pteval; - unsigned long vpn; - struct page *page; - unsigned long pfn = pte_pfn(pte); - struct address_space *mapping; - - if (!pfn_valid(pfn)) - return; - - page = pfn_to_page(pfn); - mapping = page_mapping(page); - if (mapping) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - - if (dirty) - __flush_wback_region((void *)P1SEGADDR(phys), - PAGE_SIZE); - } - - local_irq_save(flags); - - /* Set PTEH register */ - vpn = (address & MMU_VPN_MASK) | get_asid(); - ctrl_outl(vpn, MMU_PTEH); - - pteval = pte_val(pte); - -#ifdef CONFIG_CPU_HAS_PTEA - /* Set PTEA register */ - /* TODO: make this look less hacky */ - ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); -#endif - - /* Set PTEL register */ - pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ -#if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4) - pteval |= _PAGE_WT; -#endif - /* conveniently, we want all the software flags to be 0 anyway */ - ctrl_outl(pteval, MMU_PTEL); - - /* Load the TLB */ - asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); - local_irq_restore(flags); -} diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index e5e76eb..7fbfd5a 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -8,9 +8,69 @@ * * Released under the terms of the GNU GPL v2.0. */ -#include <linux/io.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/interrupt.h> + #include <asm/system.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/pgalloc.h> #include <asm/mmu_context.h> +#include <asm/cacheflush.h> + +void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + unsigned long pteval; + unsigned long vpn; + + /* Ptrace may call this routine. */ + if (vma && current->active_mm != vma->vm_mm) + return; + +#if defined(CONFIG_SH7705_CACHE_32KB) + { + struct page *page = pte_page(pte); + unsigned long pfn = pte_pfn(pte); + + if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + + __flush_wback_region((void *)P1SEGADDR(phys), + PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); + } + } +#endif + + local_irq_save(flags); + + /* Set PTEH register */ + vpn = (address & MMU_VPN_MASK) | get_asid(); + ctrl_outl(vpn, MMU_PTEH); + + pteval = pte_val(pte); + + /* Set PTEL register */ + pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ + /* conveniently, we want all the software flags to be 0 anyway */ + ctrl_outl(pteval, MMU_PTEL); + + /* Load the TLB */ + asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); + local_irq_restore(flags); +} void local_flush_tlb_one(unsigned long asid, unsigned long page) { @@ -34,3 +94,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) for (i = 0; i < ways; i++) ctrl_outl(data, addr + (i << 8)); } + diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index 221e709..f74cf66 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c @@ -8,9 +8,74 @@ * * Released under the terms of the GNU GPL v2.0. */ -#include <linux/io.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/interrupt.h> + #include <asm/system.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/pgalloc.h> #include <asm/mmu_context.h> +#include <asm/cacheflush.h> + +void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + unsigned long pteval; + unsigned long vpn; + struct page *page; + unsigned long pfn; + + /* Ptrace may call this routine. */ + if (vma && current->active_mm != vma->vm_mm) + return; + + pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + page = pfn_to_page(pfn); + if (!test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); + } + } + + local_irq_save(flags); + + /* Set PTEH register */ + vpn = (address & MMU_VPN_MASK) | get_asid(); + ctrl_outl(vpn, MMU_PTEH); + + pteval = pte_val(pte); + + /* Set PTEA register */ + if (cpu_data->flags & CPU_HAS_PTEA) + /* TODO: make this look less hacky */ + ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); + + /* Set PTEL register */ + pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ +#ifdef CONFIG_SH_WRITETHROUGH + pteval |= _PAGE_WT; +#endif + /* conveniently, we want all the software flags to be 0 anyway */ + ctrl_outl(pteval, MMU_PTEL); + + /* Load the TLB */ + asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); + local_irq_restore(flags); +} void local_flush_tlb_one(unsigned long asid, unsigned long page) { @@ -28,3 +93,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) ctrl_outl(data, addr); back_to_P1(); } + diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 310af0f..021b82c 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -56,30 +56,31 @@ static int connect_to_switch(struct daemon_data *pri) pri->control = socket(AF_UNIX, SOCK_STREAM, 0); if(pri->control < 0){ + err = -errno; printk("daemon_open : control socket failed, errno = %d\n", - errno); - return(-errno); + -err); + return err; } if(connect(pri->control, (struct sockaddr *) ctl_addr, sizeof(*ctl_addr)) < 0){ - printk("daemon_open : control connect failed, errno = %d\n", - errno); err = -errno; + printk("daemon_open : control connect failed, errno = %d\n", + -err); goto out; } fd = socket(AF_UNIX, SOCK_DGRAM, 0); if(fd < 0){ - printk("daemon_open : data socket failed, errno = %d\n", - errno); err = -errno; + printk("daemon_open : data socket failed, errno = %d\n", + -err); goto out; } if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ - printk("daemon_open : data bind failed, errno = %d\n", - errno); err = -errno; + printk("daemon_open : data bind failed, errno = %d\n", + -err); goto out_close; } diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 01d4ab6..f75d7b0 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -370,10 +370,10 @@ static irqreturn_t line_write_interrupt(int irq, void *data) struct tty_struct *tty = line->tty; int err; - /* Interrupts are enabled here because we registered the interrupt with + /* Interrupts are disabled here because we registered the interrupt with * IRQF_DISABLED (see line_setup_irq).*/ - spin_lock_irq(&line->lock); + spin_lock(&line->lock); err = flush_buffer(line); if (err == 0) { return IRQ_NONE; @@ -381,7 +381,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) line->head = line->buffer; line->tail = line->buffer; } - spin_unlock_irq(&line->lock); + spin_unlock(&line->lock); if(tty == NULL) return IRQ_NONE; diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 8138f5e..b827e82 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -50,6 +50,14 @@ static void mcast_user_init(void *data, void *dev) pri->dev = dev; } +static void mcast_remove(void *data) +{ + struct mcast_data *pri = data; + + kfree(pri->mcast_addr); + pri->mcast_addr = NULL; +} + static int mcast_open(void *data) { struct mcast_data *pri = data; @@ -157,7 +165,7 @@ const struct net_user_info mcast_user_info = { .init = mcast_user_init, .open = mcast_open, .close = mcast_close, - .remove = NULL, + .remove = mcast_remove, .set_mtu = mcast_set_mtu, .add_address = NULL, .delete_address = NULL, diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index fc22b9b..4b382a6 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -179,7 +179,7 @@ static struct console ssl_cons = { .write = ssl_console_write, .device = ssl_console_device, .setup = ssl_console_setup, - .flags = CON_PRINTBUFFER, + .flags = CON_PRINTBUFFER|CON_ANYTIME, .index = -1, }; diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 7ff0b0f..76d1f1c 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -153,7 +153,7 @@ static struct console stdiocons = { .write = uml_console_write, .device = uml_console_device, .setup = uml_console_setup, - .flags = CON_PRINTBUFFER, + .flags = CON_PRINTBUFFER|CON_ANYTIME, .index = -1, }; diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 8629bd1..5c74da4 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -192,7 +192,9 @@ extern int os_process_parent(int pid); extern void os_stop_process(int pid); extern void os_kill_process(int pid, int reap_child); extern void os_kill_ptraced_process(int pid, int reap_child); +#ifdef UML_CONFIG_MODE_TT extern void os_usr1_process(int pid); +#endif extern long os_ptrace_ldt(long pid, long addr, long data); extern int os_getpid(void); @@ -261,7 +263,6 @@ extern void block_signals(void); extern void unblock_signals(void); extern int get_signals(void); extern int set_signals(int enable); -extern void os_usr1_signal(int on); /* trap.c */ extern void os_fill_handlinfo(struct kern_handlers h); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 50a288b..dbf2f5b 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -142,6 +142,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) .events = events, .current_events = 0 } ); + err = -EBUSY; spin_lock_irqsave(&irq_lock, flags); for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { if ((irq_fd->fd == fd) && (irq_fd->type == type)) { diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index c692a19..76bdd67 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -21,6 +21,7 @@ #include "longjmp.h" #include "skas_ptrace.h" #include "kern_constants.h" +#include "uml-config.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -131,10 +132,12 @@ void os_kill_ptraced_process(int pid, int reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); } +#ifdef UML_CONFIG_MODE_TT void os_usr1_process(int pid) { kill(pid, SIGUSR1); } +#endif /* Don't use the glibc version, which caches the result in TLS. It misses some * syscalls, and also breaks with clone(), which does not unshare the TLS. diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index b897e85..2667686 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -243,8 +243,3 @@ int set_signals(int enable) return ret; } - -void os_usr1_signal(int on) -{ - change_sig(SIGUSR1, on); -} diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 01b91f9..b3f6350 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -103,6 +103,9 @@ long arch_prctl_skas(struct task_struct *task, int code, switch(code){ case ARCH_SET_FS: + current->thread.arch.fs = (unsigned long) ptr; + save_registers(pid, ¤t->thread.regs.regs); + break; case ARCH_SET_GS: save_registers(pid, ¤t->thread.regs.regs); break; @@ -140,9 +143,8 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) { - if(to->thread.arch.fs == 0) + if((to->thread.arch.fs == 0) || (to->mm == NULL)) return; arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); } - diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 04566fe..4de3a543 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -243,6 +243,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SINGLESTEP: case PTRACE_DETACH: case PTRACE_SYSCALL: + case PTRACE_OLDSETOPTIONS: case PTRACE_SETOPTIONS: case PTRACE_SET_THREAD_AREA: case PTRACE_GET_THREAD_AREA: diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c index 8047ea8..dec587b 100644 --- a/arch/x86_64/kernel/early-quirks.c +++ b/arch/x86_64/kernel/early-quirks.c @@ -30,11 +30,8 @@ static void via_bugs(void) #ifdef CONFIG_ACPI -static int nvidia_hpet_detected __initdata; - static int __init nvidia_hpet_check(struct acpi_table_header *header) { - nvidia_hpet_detected = 1; return 0; } #endif @@ -52,11 +49,7 @@ static void nvidia_bugs(void) if (acpi_use_timer_override) return; - nvidia_hpet_detected = 0; - if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) - return; - - if (nvidia_hpet_detected == 0) { + if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { acpi_skip_timer_override = 1; printk(KERN_INFO "Nvidia board " "detected. Ignoring ACPI " diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 3544372..cd4643a 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -923,8 +923,9 @@ void __init smp_prepare_boot_cpu(void) */ int __cpuinit __cpu_up(unsigned int cpu) { - int err; int apicid = cpu_present_to_apicid(cpu); + unsigned long flags; + int err; WARN_ON(irqs_disabled()); @@ -958,7 +959,9 @@ int __cpuinit __cpu_up(unsigned int cpu) /* * Make sure and check TSC sync: */ + local_irq_save(flags); check_tsc_sync_source(cpu); + local_irq_restore(flags); while (!cpu_isset(cpu, cpu_online_map)) cpu_relax(); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index d14a48e..019d8ff 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -34,6 +34,13 @@ struct taskfile_array { u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ }; +/* + * Helper - belongs in the PCI layer somewhere eventually + */ +static int is_pci_dev(struct device *dev) +{ + return (dev->bus == &pci_bus_type); +} /** * sata_get_dev_handle - finds acpi_handle and PCI device.function @@ -53,6 +60,9 @@ static int sata_get_dev_handle(struct device *dev, acpi_handle *handle, struct pci_dev *pci_dev; acpi_integer addr; + if (!is_pci_dev(dev)) + return -ENODEV; + pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */ /* Please refer to the ACPI spec for the syntax of _ADR. */ addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); @@ -84,7 +94,12 @@ static int pata_get_dev_handle(struct device *dev, acpi_handle *handle, acpi_status status; struct acpi_device_info *dinfo = NULL; int ret = -ENODEV; - struct pci_dev *pdev = to_pci_dev(dev); + struct pci_dev *pdev; + + if (!is_pci_dev(dev)) + return -ENODEV; + + pdev = to_pci_dev(dev); bus = pdev->bus->number; devnum = PCI_SLOT(pdev->devfn); diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c index 6d58b03..59146e3 100644 --- a/drivers/char/ds1286.c +++ b/drivers/char/ds1286.c @@ -197,6 +197,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file, hrs = alm_tm.tm_hour; min = alm_tm.tm_min; + sec = alm_tm.tm_sec; if (hrs >= 24) hrs = 0xff; @@ -204,9 +205,11 @@ static int ds1286_ioctl(struct inode *inode, struct file *file, if (min >= 60) min = 0xff; - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); + if (sec != 0) + return -EINVAL; + + min = BIN2BCD(min); + min = BIN2BCD(hrs); spin_lock(&ds1286_lock); rtc_write(hrs, RTC_HOURS_ALARM); diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index a44db75..a905f78 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); */ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data) { - struct cn_callback_entry *__cbq; + struct cn_callback_entry *__cbq, *__new_cbq; struct cn_dev *dev = &cdev; int err = -ENODEV; @@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v } else { struct cn_callback_data *d; - __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); - if (__cbq) { - d = &__cbq->data; + err = -ENOMEM; + __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); + if (__new_cbq) { + d = &__new_cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = __cbq; + d->free = __new_cbq; - INIT_WORK(&__cbq->work, + INIT_WORK(&__new_cbq->work, &cn_queue_wrapper); - + if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + &__new_cbq->work)) err = 0; else { - kfree(__cbq); + kfree(__new_cbq); err = -EINVAL; } - } else - err = -ENOMEM; + } } break; } diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d441815..fde92ce 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1821,7 +1821,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, struct rdma_bind_list *bind_list; int port, ret; - bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL); + bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); if (!bind_list) return -ENOMEM; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index b516b93..c859134 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -266,7 +266,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, mutex_lock(&ctx->file->mut); if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) { if (!ctx->backlog) { - ret = -EDQUOT; + ret = -ENOMEM; kfree(uevent); goto out; } diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index d737c73..818cf1a 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -36,6 +36,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include "cxio_resource.h" #include "cxio_hal.h" diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index b21fde8..d0ed1d3 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -305,8 +305,7 @@ static int status2errno(int status) */ static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) { - if (skb) { - BUG_ON(skb_cloned(skb)); + if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { skb_trim(skb, 0); skb_get(skb); } else { @@ -1415,6 +1414,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) wake_up(&ep->com.waitq); break; case FPDU_MODE: + start_ep_timer(ep); __state_set(&ep->com, CLOSING); attrs.next_state = IWCH_QP_STATE_CLOSING; iwch_modify_qp(ep->com.qp->rhp, ep->com.qp, @@ -1425,7 +1425,6 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) disconnect = 0; break; case CLOSING: - start_ep_timer(ep); __state_set(&ep->com, MORIBUND); disconnect = 0; break; @@ -1487,8 +1486,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) case CONNECTING: break; case MPA_REQ_WAIT: + stop_ep_timer(ep); break; case MPA_REQ_SENT: + stop_ep_timer(ep); connect_reply_upcall(ep, -ECONNRESET); break; case MPA_REP_SENT: @@ -1507,9 +1508,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) get_ep(&ep->com); break; case MORIBUND: + case CLOSING: stop_ep_timer(ep); + /*FALLTHROUGH*/ case FPDU_MODE: - case CLOSING: if (ep->com.cm_id && ep->com.qp) { attrs.next_state = IWCH_QP_STATE_ERROR; ret = iwch_modify_qp(ep->com.qp->rhp, @@ -1570,7 +1572,6 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) spin_lock_irqsave(&ep->com.lock, flags); switch (ep->com.state) { case CLOSING: - start_ep_timer(ep); __state_set(&ep->com, MORIBUND); break; case MORIBUND: @@ -1586,6 +1587,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) __state_set(&ep->com, DEAD); release = 1; break; + case ABORTING: + break; case DEAD: default: BUG_ON(1); @@ -1659,6 +1662,7 @@ static void ep_timeout(unsigned long arg) break; case MPA_REQ_WAIT: break; + case CLOSING: case MORIBUND: if (ep->com.cm_id && ep->com.qp) { attrs.next_state = IWCH_QP_STATE_ERROR; @@ -1687,12 +1691,11 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) return -ECONNRESET; } BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); - state_set(&ep->com, CLOSING); if (mpa_rev == 0) abort_connection(ep, NULL, GFP_KERNEL); else { err = send_mpa_reject(ep, pdata, pdata_len); - err = send_halfclose(ep, GFP_KERNEL); + err = iwch_ep_disconnect(ep, 0, GFP_KERNEL); } return 0; } @@ -1957,11 +1960,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp) case MPA_REQ_RCVD: case MPA_REP_SENT: case FPDU_MODE: + start_ep_timer(ep); ep->com.state = CLOSING; close = 1; break; case CLOSING: - start_ep_timer(ep); ep->com.state = MORIBUND; close = 1; break; diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c index 54362af..b406766 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_ev.c +++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c @@ -47,12 +47,6 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, struct iwch_qp_attributes attrs; struct iwch_qp *qhp; - printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x " - "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__, - CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe), - CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe), - CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe)); - spin_lock(&rnicp->lock); qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe)); @@ -73,6 +67,12 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, return; } + printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x " + "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__, + CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe), + CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe), + CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe)); + atomic_inc(&qhp->refcnt); spin_unlock(&rnicp->lock); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index 9947a14..f2774ae 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -331,6 +331,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) int ret = 0; struct iwch_mm_entry *mm; struct iwch_ucontext *ucontext; + u64 addr; PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff, key, len); @@ -345,10 +346,11 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) mm = remove_mmap(ucontext, key, len); if (!mm) return -EINVAL; + addr = mm->addr; kfree(mm); - if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) && - (mm->addr < (rdev_p->rnic_info.udbell_physbase + + if ((addr >= rdev_p->rnic_info.udbell_physbase) && + (addr < (rdev_p->rnic_info.udbell_physbase + rdev_p->rnic_info.udbell_len))) { /* @@ -362,7 +364,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; vma->vm_flags &= ~VM_MAYREAD; ret = io_remap_pfn_range(vma, vma->vm_start, - mm->addr >> PAGE_SHIFT, + addr >> PAGE_SHIFT, len, vma->vm_page_prot); } else { @@ -370,7 +372,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) * Map WQ or CQ contig dma memory... */ ret = remap_pfn_range(vma, vma->vm_start, - mm->addr >> PAGE_SHIFT, + addr >> PAGE_SHIFT, len, vma->vm_page_prot); } @@ -463,9 +465,6 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd, php = to_iwch_pd(pd); rhp = php->rhp; - acc = iwch_convert_access(acc); - - mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); if (!mhp) return ERR_PTR(-ENOMEM); @@ -491,12 +490,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd, mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; - /* NOTE: TPT perms are backwards from BIND WR perms! */ - mhp->attr.perms = (acc & 0x1) << 3; - mhp->attr.perms |= (acc & 0x2) << 1; - mhp->attr.perms |= (acc & 0x4) >> 1; - mhp->attr.perms |= (acc & 0x8) >> 3; - + mhp->attr.perms = iwch_ib_to_tpt_access(acc); mhp->attr.va_fbo = *iova_start; mhp->attr.page_size = shift - 12; @@ -525,7 +519,6 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, struct iwch_mr mh, *mhp; struct iwch_pd *php; struct iwch_dev *rhp; - int new_acc; __be64 *page_list = NULL; int shift = 0; u64 total_size; @@ -546,14 +539,12 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, if (rhp != php->rhp) return -EINVAL; - new_acc = mhp->attr.perms; - memcpy(&mh, mhp, sizeof *mhp); if (mr_rereg_mask & IB_MR_REREG_PD) php = to_iwch_pd(pd); if (mr_rereg_mask & IB_MR_REREG_ACCESS) - mh.attr.perms = iwch_convert_access(acc); + mh.attr.perms = iwch_ib_to_tpt_access(acc); if (mr_rereg_mask & IB_MR_REREG_TRANS) ret = build_phys_page_list(buffer_list, num_phys_buf, iova_start, @@ -568,7 +559,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, if (mr_rereg_mask & IB_MR_REREG_PD) mhp->attr.pdid = php->pdid; if (mr_rereg_mask & IB_MR_REREG_ACCESS) - mhp->attr.perms = acc; + mhp->attr.perms = iwch_ib_to_tpt_access(acc); if (mr_rereg_mask & IB_MR_REREG_TRANS) { mhp->attr.zbva = 0; mhp->attr.va_fbo = *iova_start; @@ -613,8 +604,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, goto err; } - acc = iwch_convert_access(acc); - i = n = 0; list_for_each_entry(chunk, ®ion->chunk_list, list) @@ -630,10 +619,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, mhp->rhp = rhp; mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; - mhp->attr.perms = (acc & 0x1) << 3; - mhp->attr.perms |= (acc & 0x2) << 1; - mhp->attr.perms |= (acc & 0x4) >> 1; - mhp->attr.perms |= (acc & 0x8) >> 3; + mhp->attr.perms = iwch_ib_to_tpt_access(acc); mhp->attr.va_fbo = region->virt_base; mhp->attr.page_size = shift - 12; mhp->attr.len = (u32) region->length; @@ -736,10 +722,8 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp) qhp = to_iwch_qp(ib_qp); rhp = qhp->rhp; - if (qhp->attr.state == IWCH_QP_STATE_RTS) { - attrs.next_state = IWCH_QP_STATE_ERROR; - iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0); - } + attrs.next_state = IWCH_QP_STATE_ERROR; + iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0); wait_event(qhp->wait, !qhp->ep); remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h index de0fe1b..93bcc56 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -286,27 +286,20 @@ static inline int iwch_convert_state(enum ib_qp_state ib_state) } } -enum iwch_mem_perms { - IWCH_MEM_ACCESS_LOCAL_READ = 1 << 0, - IWCH_MEM_ACCESS_LOCAL_WRITE = 1 << 1, - IWCH_MEM_ACCESS_REMOTE_READ = 1 << 2, - IWCH_MEM_ACCESS_REMOTE_WRITE = 1 << 3, - IWCH_MEM_ACCESS_ATOMICS = 1 << 4, - IWCH_MEM_ACCESS_BINDING = 1 << 5, - IWCH_MEM_ACCESS_LOCAL = - (IWCH_MEM_ACCESS_LOCAL_READ | IWCH_MEM_ACCESS_LOCAL_WRITE), - IWCH_MEM_ACCESS_REMOTE = - (IWCH_MEM_ACCESS_REMOTE_WRITE | IWCH_MEM_ACCESS_REMOTE_READ) - /* cannot go beyond 1 << 31 */ -} __attribute__ ((packed)); - -static inline u32 iwch_convert_access(int acc) +static inline u32 iwch_ib_to_tpt_access(int acc) { - return (acc & IB_ACCESS_REMOTE_WRITE ? IWCH_MEM_ACCESS_REMOTE_WRITE : 0) - | (acc & IB_ACCESS_REMOTE_READ ? IWCH_MEM_ACCESS_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? IWCH_MEM_ACCESS_LOCAL_WRITE : 0) | - (acc & IB_ACCESS_MW_BIND ? IWCH_MEM_ACCESS_BINDING : 0) | - IWCH_MEM_ACCESS_LOCAL_READ; + return (acc & IB_ACCESS_REMOTE_WRITE ? TPT_REMOTE_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? TPT_REMOTE_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? TPT_LOCAL_WRITE : 0) | + TPT_LOCAL_READ; +} + +static inline u32 iwch_ib_to_mwbind_access(int acc) +{ + return (acc & IB_ACCESS_REMOTE_WRITE ? T3_MEM_ACCESS_REM_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? T3_MEM_ACCESS_REM_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? T3_MEM_ACCESS_LOCAL_WRITE : 0) | + T3_MEM_ACCESS_LOCAL_READ; } enum iwch_mmid_state { diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 9ea00cc..0a472c9 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -439,7 +439,7 @@ int iwch_bind_mw(struct ib_qp *qp, wqe->bind.type = T3_VA_BASED_TO; /* TBD: check perms */ - wqe->bind.perms = iwch_convert_access(mw_bind->mw_access_flags); + wqe->bind.perms = iwch_ib_to_mwbind_access(mw_bind->mw_access_flags); wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey); wqe->bind.mw_stag = cpu_to_be32(mw->rkey); wqe->bind.mw_len = cpu_to_be32(mw_bind->length); diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 40404c9..82ded44 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -52,6 +52,8 @@ struct ehca_mw; struct ehca_pd; struct ehca_av; +#include <linux/wait.h> + #include <rdma/ib_verbs.h> #include <rdma/ib_user_verbs.h> @@ -153,7 +155,9 @@ struct ehca_cq { spinlock_t cb_lock; struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; struct list_head entry; - u32 nr_callbacks; + u32 nr_callbacks; /* #events assigned to cpu by scaling code */ + u32 nr_events; /* #events seen */ + wait_queue_head_t wait_completion; spinlock_t task_lock; u32 ownpid; /* mmap counter for resources mapped into user space */ diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 6ebfa27..e2cdc1a 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c @@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, spin_lock_init(&my_cq->spinlock); spin_lock_init(&my_cq->cb_lock); spin_lock_init(&my_cq->task_lock); + init_waitqueue_head(&my_cq->wait_completion); my_cq->ownpid = current->tgid; cq = &my_cq->ib_cq; @@ -302,6 +303,16 @@ create_cq_exit1: return cq; } +static int get_cq_nr_events(struct ehca_cq *my_cq) +{ + int ret; + unsigned long flags; + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + ret = my_cq->nr_events; + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + return ret; +} + int ehca_destroy_cq(struct ib_cq *cq) { u64 h_ret; @@ -329,10 +340,11 @@ int ehca_destroy_cq(struct ib_cq *cq) } spin_lock_irqsave(&ehca_cq_idr_lock, flags); - while (my_cq->nr_callbacks) { + while (my_cq->nr_events) { spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - yield(); + wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq)); spin_lock_irqsave(&ehca_cq_idr_lock, flags); + /* recheck nr_events to assure no cqe has just arrived */ } idr_remove(&ehca_cq_idr, my_cq->token); diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 3ec53c6..20f36bf 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -404,10 +404,11 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) u32 token; unsigned long flags; struct ehca_cq *cq; + eqe_value = eqe->entry; ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value); if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) { - ehca_dbg(&shca->ib_device, "... completion event"); + ehca_dbg(&shca->ib_device, "Got completion event"); token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); spin_lock_irqsave(&ehca_cq_idr_lock, flags); cq = idr_find(&ehca_cq_idr, token); @@ -419,16 +420,20 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) return; } reset_eq_pending(cq); - if (ehca_scaling_code) { + cq->nr_events++; + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + if (ehca_scaling_code) queue_comp_task(cq); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - } else { - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + else { comp_event_callback(cq); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); } } else { - ehca_dbg(&shca->ib_device, - "Got non completion event"); + ehca_dbg(&shca->ib_device, "Got non completion event"); parse_identifier(shca, eqe_value); } } @@ -478,6 +483,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) "token=%x", token); continue; } + eqe_cache[eqe_cnt].cq->nr_events++; spin_unlock(&ehca_cq_idr_lock); } else eqe_cache[eqe_cnt].cq = NULL; @@ -504,12 +510,18 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) /* call completion handler for cached eqes */ for (i = 0; i < eqe_cnt; i++) if (eq->eqe_cache[i].cq) { - if (ehca_scaling_code) { - spin_lock(&ehca_cq_idr_lock); + if (ehca_scaling_code) queue_comp_task(eq->eqe_cache[i].cq); - spin_unlock(&ehca_cq_idr_lock); - } else - comp_event_callback(eq->eqe_cache[i].cq); + else { + struct ehca_cq *cq = eq->eqe_cache[i].cq; + comp_event_callback(cq); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, + flags); + } } else { ehca_dbg(&shca->ib_device, "Got non completion event"); parse_identifier(shca, eq->eqe_cache[i].eqe->entry); @@ -523,7 +535,6 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) if (!eqe) break; process_eqe(shca, eqe); - eqe_cnt++; } while (1); unlock_irq_spinlock: @@ -567,8 +578,7 @@ static void __queue_comp_task(struct ehca_cq *__cq, list_add_tail(&__cq->entry, &cct->cq_list); cct->cq_jobs++; wake_up(&cct->wait_queue); - } - else + } else __cq->nr_callbacks++; spin_unlock(&__cq->task_lock); @@ -577,18 +587,21 @@ static void __queue_comp_task(struct ehca_cq *__cq, static void queue_comp_task(struct ehca_cq *__cq) { - int cpu; int cpu_id; struct ehca_cpu_comp_task *cct; + int cq_jobs; + unsigned long flags; - cpu = get_cpu(); cpu_id = find_next_online_cpu(pool); BUG_ON(!cpu_online(cpu_id)); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); BUG_ON(!cct); - if (cct->cq_jobs > 0) { + spin_lock_irqsave(&cct->task_lock, flags); + cq_jobs = cct->cq_jobs; + spin_unlock_irqrestore(&cct->task_lock, flags); + if (cq_jobs > 0) { cpu_id = find_next_online_cpu(pool); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); BUG_ON(!cct); @@ -608,11 +621,17 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct) cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); spin_unlock_irqrestore(&cct->task_lock, flags); comp_event_callback(cq); - spin_lock_irqsave(&cct->task_lock, flags); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + + spin_lock_irqsave(&cct->task_lock, flags); spin_lock(&cq->task_lock); cq->nr_callbacks--; - if (cq->nr_callbacks == 0) { + if (!cq->nr_callbacks) { list_del_init(cct->cq_list.next); cct->cq_jobs--; } diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index c183512..059da96 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0021"); +MODULE_VERSION("SVNEHCA_0022"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -810,7 +810,7 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0021)\n"); + "(Rel.: SVNEHCA_0022)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 71dc84b..1c6b63a 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1088,21 +1088,21 @@ static void mthca_unmap_memfree(struct mthca_dev *dev, static int mthca_alloc_memfree(struct mthca_dev *dev, struct mthca_qp *qp) { - int ret = 0; - if (mthca_is_memfree(dev)) { qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ, qp->qpn, &qp->rq.db); if (qp->rq.db_index < 0) - return ret; + return -ENOMEM; qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ, qp->qpn, &qp->sq.db); - if (qp->sq.db_index < 0) + if (qp->sq.db_index < 0) { mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index); + return -ENOMEM; + } } - return ret; + return 0; } static void mthca_free_memfree(struct mthca_dev *dev, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index bb2e3d5..56c87a8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -407,6 +407,10 @@ static int ipoib_mcast_join_complete(int status, queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); + + if (mcast == priv->broadcast) + netif_carrier_on(dev); + return 0; } @@ -594,7 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work) ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); clear_bit(IPOIB_MCAST_RUN, &priv->flags); - netif_carrier_on(dev); } int ipoib_mcast_start_thread(struct net_device *dev) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index 3cb551b..7f3ec20 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -259,12 +259,13 @@ void ipoib_event(struct ib_event_handler *handler, struct ipoib_dev_priv *priv = container_of(handler, struct ipoib_dev_priv, event_handler); - if (record->event == IB_EVENT_PORT_ERR || - record->event == IB_EVENT_PKEY_CHANGE || - record->event == IB_EVENT_PORT_ACTIVE || - record->event == IB_EVENT_LID_CHANGE || - record->event == IB_EVENT_SM_CHANGE || - record->event == IB_EVENT_CLIENT_REREGISTER) { + if ((record->event == IB_EVENT_PORT_ERR || + record->event == IB_EVENT_PKEY_CHANGE || + record->event == IB_EVENT_PORT_ACTIVE || + record->event == IB_EVENT_LID_CHANGE || + record->event == IB_EVENT_SM_CHANGE || + record->event == IB_EVENT_CLIENT_REREGISTER) && + record->element.port_num == priv->port) { ipoib_dbg(priv, "Port state change event\n"); queue_work(ipoib_workqueue, &priv->flush_task); } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ec195a3..db9cca3 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -553,7 +553,8 @@ static int __devinit i8042_check_aux(void) */ param = 0x5a; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x5a) { + retval = i8042_command(¶m, I8042_CMD_AUX_LOOP); + if (retval || param != 0x5a) { /* * External connection test - filters out AT-soldered PS/2 i8042's @@ -567,7 +568,12 @@ static int __devinit i8042_check_aux(void) (param && param != 0xfa && param != 0xff)) return -1; - aux_loop_broken = 1; +/* + * If AUX_LOOP completed without error but returned unexpected data + * mark it as broken + */ + if (!retval) + aux_loop_broken = 1; } /* diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7299577..b406ecf 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -858,19 +858,7 @@ static struct eisa_device_id vortex_eisa_ids[] = { }; MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids); -static int vortex_eisa_probe(struct device *device); -static int vortex_eisa_remove(struct device *device); - -static struct eisa_driver vortex_eisa_driver = { - .id_table = vortex_eisa_ids, - .driver = { - .name = "3c59x", - .probe = vortex_eisa_probe, - .remove = vortex_eisa_remove - } -}; - -static int vortex_eisa_probe(struct device *device) +static int __init vortex_eisa_probe(struct device *device) { void __iomem *ioaddr; struct eisa_device *edev; @@ -893,7 +881,7 @@ static int vortex_eisa_probe(struct device *device) return 0; } -static int vortex_eisa_remove(struct device *device) +static int __devexit vortex_eisa_remove(struct device *device) { struct eisa_device *edev; struct net_device *dev; @@ -918,7 +906,17 @@ static int vortex_eisa_remove(struct device *device) free_netdev(dev); return 0; } -#endif + +static struct eisa_driver vortex_eisa_driver = { + .id_table = vortex_eisa_ids, + .driver = { + .name = "3c59x", + .probe = vortex_eisa_probe, + .remove = __devexit_p(vortex_eisa_remove) + } +}; + +#endif /* CONFIG_EISA */ /* returns count found (>= 0), or negative on error */ static int __init vortex_eisa_init(void) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9ba21e0..1ee27c3 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -787,6 +787,12 @@ static int mv643xx_eth_open(struct net_device *dev) unsigned int size; int err; + /* Clear any pending ethernet port interrupts */ + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + /* wait for previous write to complete */ + mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)); + err = request_irq(dev->irq, mv643xx_eth_int_handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (err) { @@ -875,10 +881,6 @@ static int mv643xx_eth_open(struct net_device *dev) mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */ - /* Clear any pending ethernet port interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); - eth_port_start(dev); /* Interrupt Coalescing */ diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b05dc6e..ac02b3b 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -181,6 +181,7 @@ struct myri10ge_priv { int intr_coal_delay; __be32 __iomem *intr_coal_delay_ptr; int mtrr; + int wc_enabled; int wake_queue; int stop_queue; int down_cnt; @@ -717,6 +718,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) int status; size_t bytes; u32 len; + struct page *dmatest_page; + dma_addr_t dmatest_bus; /* try to send a reset command to the card to see if it * is alive */ @@ -726,6 +729,11 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_err(&mgp->pdev->dev, "failed reset\n"); return -ENXIO; } + dmatest_page = alloc_page(GFP_KERNEL); + if (!dmatest_page) + return -ENOMEM; + dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); /* Now exchange information about interrupts */ @@ -764,8 +772,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) len = mgp->tx.boundary; - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x10000; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -774,8 +782,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) else dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n", status); - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x1; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -785,8 +793,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n", status); - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x10001; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -796,6 +804,9 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_warn(&mgp->pdev->dev, "DMA read/write benchmark failed: %d\n", status); + pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); + put_page(dmatest_page); + memset(mgp->rx_done.entry, 0, bytes); /* reset mcp/driver shared state back to 0 */ @@ -1375,7 +1386,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i] = ((unsigned long *)&mgp->stats)[i]; data[i++] = (unsigned int)mgp->tx.boundary; - data[i++] = (unsigned int)(mgp->mtrr >= 0); + data[i++] = (unsigned int)mgp->wc_enabled; data[i++] = (unsigned int)mgp->pdev->irq; data[i++] = (unsigned int)mgp->msi_enabled; data[i++] = (unsigned int)mgp->read_dma; @@ -1456,6 +1467,8 @@ static int myri10ge_allocate_rings(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); tx_ring_size = cmd.data0; status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); + if (status != 0) + return status; rx_ring_size = cmd.data0; tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send); @@ -1463,6 +1476,8 @@ static int myri10ge_allocate_rings(struct net_device *dev) mgp->tx.mask = tx_ring_entries - 1; mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1; + status = -ENOMEM; + /* allocate the host shadow rings */ bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4) @@ -1735,7 +1750,7 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_irq; } - if (myri10ge_wcfifo && mgp->mtrr >= 0) { + if (myri10ge_wcfifo && mgp->wc_enabled) { mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4; mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL; @@ -2510,6 +2525,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) bridge->vendor, bridge->device); mgp->tx.boundary = 4096; mgp->fw_name = myri10ge_fw_aligned; + } else if (bridge && + bridge->vendor == PCI_VENDOR_ID_SGI && + bridge->device == 0x4002 /* TIOCE pcie-port */ ) { + /* this pcie bridge does not support 4K rdma request */ + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_aligned; } } else { if (myri10ge_force_firmware == 1) { @@ -2830,9 +2851,12 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp->board_span = pci_resource_len(pdev, 0); mgp->iomem_base = pci_resource_start(pdev, 0); mgp->mtrr = -1; + mgp->wc_enabled = 0; #ifdef CONFIG_MTRR mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span, MTRR_TYPE_WRCOMB, 1); + if (mgp->mtrr >= 0) + mgp->wc_enabled = 1; #endif /* Hack. need to get rid of these magic numbers */ mgp->sram_size = @@ -2927,7 +2951,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n", (mgp->msi_enabled ? "MSI" : "xPIC"), netdev->irq, mgp->tx.boundary, mgp->fw_name, - (mgp->mtrr >= 0 ? "Enabled" : "Disabled")); + (mgp->wc_enabled ? "Enabled" : "Disabled")); return 0; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index a2877f3..1be5570 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -228,7 +228,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) &adapter->ctx_desc_pdev); printk("ctx_desc_phys_addr: 0x%llx\n", - (u64) adapter->ctx_desc_phys_addr); + (unsigned long long) adapter->ctx_desc_phys_addr); if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); err = -ENOMEM; @@ -247,7 +247,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) adapter->max_tx_desc_count, (dma_addr_t *) & hw->cmd_desc_phys_addr, &adapter->ahw.cmd_desc_pdev); - printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr); + printk("cmd_desc_phys_addr: 0x%llx\n", + (unsigned long long) hw->cmd_desc_phys_addr); if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 15d954e50..521b5f0 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -572,8 +572,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) { unsigned int val; - mdio_write(ioaddr, MII_BMCR, BMCR_RESET); - val = mdio_read(ioaddr, MII_BMCR); + val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; + mdio_write(ioaddr, MII_BMCR, val & 0xffff); } static void rtl8169_check_link_status(struct net_device *dev, @@ -1368,11 +1368,7 @@ static inline void rtl8169_request_timer(struct net_device *dev) (tp->phy_version >= RTL_GIGA_PHY_VER_H)) return; - init_timer(timer); - timer->expires = jiffies + RTL8169_PHY_TIMEOUT; - timer->data = (unsigned long)(dev); - timer->function = rtl8169_phy_timer; - add_timer(timer); + mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1685,6 +1681,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->mmio_addr = ioaddr; tp->align = rtl_cfg_info[ent->driver_data].align; + init_timer(&tp->timer); + tp->timer.data = (unsigned long) dev; + tp->timer.function = rtl8169_phy_timer; + spin_lock_init(&tp->lock); rc = register_netdev(dev); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 5383997..ab0ab92 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2165,9 +2165,27 @@ force_update: /* fall through */ #endif case OP_RXCHKS: - skb = sky2->rx_ring[sky2->rx_next].skb; - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = status & 0xffff; + if (!sky2->rx_csum) + break; + + /* Both checksum counters are programmed to start at + * the same offset, so unless there is a problem they + * should match. This failure is an early indication that + * hardware receive checksumming won't work. + */ + if (likely(status >> 16 == (status & 0xffff))) { + skb = sky2->rx_ring[sky2->rx_next].skb; + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = status & 0xffff; + } else { + printk(KERN_NOTICE PFX "%s: hardware receive " + "checksum problem (status = %#x)\n", + dev->name, status); + sky2->rx_csum = 0; + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[le->link], Q_CSR), + BMU_DIS_RX_CHKSUM); + } break; case OP_TXINDEXLE: diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 0d97e10..36202e9 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -186,7 +186,6 @@ static char __devinit *adapter_def(char type) #define TRC_INITV 0x02 /* verbose init trace points */ static unsigned char ibmtr_debug_trace = 0; -static int ibmtr_probe(struct net_device *dev); static int ibmtr_probe1(struct net_device *dev, int ioaddr); static unsigned char get_sram_size(struct tok_info *adapt_info); static int trdev_init(struct net_device *dev); @@ -335,17 +334,6 @@ static void ibmtr_cleanup_card(struct net_device *dev) #endif } -int ibmtr_probe_card(struct net_device *dev) -{ - int err = ibmtr_probe(dev); - if (!err) { - err = register_netdev(dev); - if (err) - ibmtr_cleanup_card(dev); - } - return err; -} - /**************************************************************************** * ibmtr_probe(): Routine specified in the network device structure * to probe for an IBM Token Ring Adapter. Routine outline: @@ -358,7 +346,7 @@ int ibmtr_probe_card(struct net_device *dev) * which references it. ****************************************************************************/ -static int ibmtr_probe(struct net_device *dev) +static int __init ibmtr_probe(struct net_device *dev) { int i; int base_addr = dev->base_addr; @@ -378,6 +366,17 @@ static int ibmtr_probe(struct net_device *dev) return -ENODEV; } +int __init ibmtr_probe_card(struct net_device *dev) +{ + int err = ibmtr_probe(dev); + if (!err) { + err = register_netdev(dev); + if (err) + ibmtr_cleanup_card(dev); + } + return err; +} + /*****************************************************************************/ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index ebbda1d..f3a972e 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -30,8 +30,8 @@ */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.4.2" -#define DRV_RELDATE "Sept-11-2006" +#define DRV_VERSION "1.4.3" +#define DRV_RELDATE "2007-03-06" /* A few user-configurable values. @@ -105,6 +105,7 @@ static const int multicast_filter_limit = 32; #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> +#include <linux/dmi.h> /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = @@ -1995,6 +1996,23 @@ static struct pci_driver rhine_driver = { .shutdown = rhine_shutdown, }; +static struct dmi_system_id __initdata rhine_dmi_table[] = { + { + .ident = "EPIA-M", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."), + DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"), + }, + }, + { + .ident = "KV7", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"), + }, + }, + { NULL } +}; static int __init rhine_init(void) { @@ -2002,6 +2020,16 @@ static int __init rhine_init(void) #ifdef MODULE printk(version); #endif + if (dmi_check_system(rhine_dmi_table)) { + /* these BIOSes fail at PXE boot if chip is in D3 */ + avoid_D3 = 1; + printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 " + "enabled.\n", + DRV_NAME); + } + else if (avoid_D3) + printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME); + return pci_register_driver(&rhine_driver); } diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index 8dbcf83..8b4540b 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -407,7 +407,7 @@ static void z8530_tx(struct z8530_channel *c) while(c->txcount) { /* FIFO full ? */ if(!(read_zsreg(c, R0)&4)) - break; + return; c->txcount--; /* * Shovel out the byte diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 253ceb8..a27e9e9 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -636,25 +636,6 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id) } /** - * sn_sal_connect_interrupt - Request interrupt, handled by sn_sal_interrupt - * @port: Our sn_cons_port (which contains the uart port) - * - * returns the console irq if interrupt is successfully registered, else 0 - * - */ -static int sn_sal_connect_interrupt(struct sn_cons_port *port) -{ - if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, - IRQF_DISABLED | IRQF_SHARED, - "SAL console driver", port) >= 0) { - return SGI_UART_VECTOR; - } - - printk(KERN_INFO "sn_console: console proceeding in polled mode\n"); - return 0; -} - -/** * sn_sal_timer_poll - this function handles polled console mode * @data: A pointer to our sn_cons_port (which contains the uart port) * @@ -746,30 +727,31 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) * mode. We were previously in asynch/polling mode (using init_timer). * * We attempt to switch to interrupt mode here by calling - * sn_sal_connect_interrupt. If that works out, we enable receive interrupts. + * request_irq. If that works out, we enable receive interrupts. */ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) { - int irq; unsigned long flags; - if (!port) - return; - - DPRINTF("sn_console: switching to interrupt driven console\n"); - - spin_lock_irqsave(&port->sc_port.lock, flags); + if (port) { + DPRINTF("sn_console: switching to interrupt driven console\n"); - irq = sn_sal_connect_interrupt(port); + if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, + IRQF_DISABLED | IRQF_SHARED, + "SAL console driver", port) >= 0) { + spin_lock_irqsave(&port->sc_port.lock, flags); + port->sc_port.irq = SGI_UART_VECTOR; + port->sc_ops = &intr_ops; - if (irq) { - port->sc_port.irq = irq; - port->sc_ops = &intr_ops; - - /* turn on receive interrupts */ - ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + /* turn on receive interrupts */ + ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + spin_unlock_irqrestore(&port->sc_port.lock, flags); + } + else { + printk(KERN_INFO + "sn_console: console proceeding in polled mode\n"); + } } - spin_unlock_irqrestore(&port->sc_port.lock, flags); } /* diff --git a/fs/compat.c b/fs/compat.c index 0ec70e3..040a8be 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -48,6 +48,7 @@ #include <linux/highmem.h> #include <linux/poll.h> #include <linux/mm.h> +#include <linux/eventpoll.h> #include <net/sock.h> /* siocdevprivate_ioctl */ @@ -2235,3 +2236,102 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) return sys_ni_syscall(); } #endif + +#ifdef CONFIG_EPOLL + +#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT +asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd, + struct compat_epoll_event __user *event) +{ + long err = 0; + struct compat_epoll_event user; + struct epoll_event __user *kernel = NULL; + + if (event) { + if (copy_from_user(&user, event, sizeof(user))) + return -EFAULT; + kernel = compat_alloc_user_space(sizeof(struct epoll_event)); + err |= __put_user(user.events, &kernel->events); + err |= __put_user(user.data, &kernel->data); + } + + return err ? err : sys_epoll_ctl(epfd, op, fd, kernel); +} + + +asmlinkage long compat_sys_epoll_wait(int epfd, + struct compat_epoll_event __user *events, + int maxevents, int timeout) +{ + long i, ret, err = 0; + struct epoll_event __user *kbuf; + struct epoll_event ev; + + if ((maxevents <= 0) || + (maxevents > (INT_MAX / sizeof(struct epoll_event)))) + return -EINVAL; + kbuf = compat_alloc_user_space(sizeof(struct epoll_event) * maxevents); + ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout); + for (i = 0; i < ret; i++) { + err |= __get_user(ev.events, &kbuf[i].events); + err |= __get_user(ev.data, &kbuf[i].data); + err |= __put_user(ev.events, &events->events); + err |= __put_user_unaligned(ev.data, &events->data); + events++; + } + + return err ? -EFAULT: ret; +} +#endif /* CONFIG_HAS_COMPAT_EPOLL_EVENT */ + +#ifdef TIF_RESTORE_SIGMASK +asmlinkage long compat_sys_epoll_pwait(int epfd, + struct compat_epoll_event __user *events, + int maxevents, int timeout, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize) +{ + long err; + compat_sigset_t csigmask; + sigset_t ksigmask, sigsaved; + + /* + * If the caller wants a certain signal mask to be set during the wait, + * we apply it here. + */ + if (sigmask) { + if (sigsetsize != sizeof(compat_sigset_t)) + return -EINVAL; + if (copy_from_user(&csigmask, sigmask, sizeof(csigmask))) + return -EFAULT; + sigset_from_compat(&ksigmask, &csigmask); + sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + +#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT + err = compat_sys_epoll_wait(epfd, events, maxevents, timeout); +#else + err = sys_epoll_wait(epfd, events, maxevents, timeout); +#endif + + /* + * If we changed the signal mask, we need to restore the original one. + * In case we've got a signal while waiting, we do not restore the + * signal mask yet, and we allow do_signal() to deliver the signal on + * the way back to userspace, before the signal mask is restored. + */ + if (sigmask) { + if (err == -EINTR) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } else + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + } + + return err; +} +#endif /* TIF_RESTORE_SIGMASK */ + +#endif /* CONFIG_EPOLL */ diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 40db61d..3870150 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -22,6 +22,7 @@ #include "lockspace.h" #include "lock.h" #include "lvb_table.h" +#include "user.h" static const char *name_prefix="dlm"; static struct miscdevice ctl_device; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index e62f3fc..1548be2 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -38,7 +38,7 @@ static struct dentry *lock_parent(struct dentry *dentry) struct dentry *dir; dir = dget(dentry->d_parent); - mutex_lock(&(dir->d_inode->i_mutex)); + mutex_lock_nested(&(dir->d_inode->i_mutex), I_MUTEX_PARENT); return dir; } diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 6618c11..12accb0 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -20,6 +20,7 @@ #include <linux/list.h> #include <linux/lm_interface.h> #include <linux/wait.h> +#include <linux/module.h> #include <linux/rwsem.h> #include <asm/uaccess.h> @@ -953,9 +954,6 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) spin_unlock(&gl->gl_spin); } - if (glops->go_drop_bh) - glops->go_drop_bh(gl); - spin_lock(&gl->gl_spin); gl->gl_req_gh = NULL; gl->gl_req_bh = NULL; diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 46af553..39c8ae2 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -245,7 +245,6 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) if (ip && S_ISREG(ip->i_inode.i_mode)) { truncate_inode_pages(ip->i_inode.i_mapping, 0); - gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages); clear_bit(GIF_PAGED, &ip->i_flags); } } @@ -459,6 +458,8 @@ const struct gfs2_glock_operations gfs2_inode_glops = { }; const struct gfs2_glock_operations gfs2_rgrp_glops = { + .go_xmote_th = meta_go_sync, + .go_drop_th = meta_go_sync, .go_inval = meta_go_inval, .go_demote_ok = rgrp_go_demote_ok, .go_lock = rgrp_go_lock, diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 12c80fd..49f0dbf 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -104,7 +104,6 @@ struct gfs2_glock_operations { void (*go_xmote_th) (struct gfs2_glock *gl); void (*go_xmote_bh) (struct gfs2_glock *gl); void (*go_drop_th) (struct gfs2_glock *gl); - void (*go_drop_bh) (struct gfs2_glock *gl); void (*go_inval) (struct gfs2_glock *gl, int flags); int (*go_demote_ok) (struct gfs2_glock *gl); int (*go_lock) (struct gfs2_holder *gh); @@ -416,7 +415,6 @@ struct gfs2_tune { unsigned int gt_stall_secs; /* Detects trouble! */ unsigned int gt_complain_secs; unsigned int gt_reclaim_limit; /* Max num of glocks in reclaim list */ - unsigned int gt_entries_per_readdir; unsigned int gt_statfs_quantum; unsigned int gt_statfs_slow; }; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 0d6831a..df0b8b3 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -43,7 +43,8 @@ static int iget_test(struct inode *inode, void *opaque) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inum_host *inum = opaque; - if (ip->i_num.no_addr == inum->no_addr) + if (ip->i_num.no_addr == inum->no_addr && + inode->i_private != NULL) return 1; return 0; @@ -61,13 +62,13 @@ static int iget_set(struct inode *inode, void *opaque) struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum) { - return ilookup5(sb, (unsigned long)inum->no_formal_ino, + return ilookup5(sb, (unsigned long)inum->no_addr, iget_test, inum); } static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum) { - return iget5_locked(sb, (unsigned long)inum->no_formal_ino, + return iget5_locked(sb, (unsigned long)inum->no_addr, iget_test, iget_set, inum); } diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 56e3359..b3b7e84 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -266,9 +266,11 @@ skip_lock: out: return error; out_unlock: - if (error == GLR_TRYFAILED) - error = AOP_TRUNCATED_PAGE; unlock_page(page); + if (error == GLR_TRYFAILED) { + error = AOP_TRUNCATED_PAGE; + yield(); + } if (do_unlock) gfs2_holder_uninit(&gh); goto out; @@ -364,6 +366,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page, if (error == GLR_TRYFAILED) { unlock_page(page); error = AOP_TRUNCATED_PAGE; + yield(); } goto out_uninit; } diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 1de05b6..aad9183 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c @@ -38,14 +38,11 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb, struct gfs2_fh_obj fh_obj; struct gfs2_inum_host *this, parent; - if (fh_type != fh_len) - return NULL; - this = &fh_obj.this; fh_obj.imode = DT_UNKNOWN; memset(&parent, 0, sizeof(struct gfs2_inum)); - switch (fh_type) { + switch (fh_len) { case GFS2_LARGE_FH_SIZE: parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; parent.no_formal_ino |= be32_to_cpu(fh[5]); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ee80b8a..ee54cb6 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -840,7 +840,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) } printk(KERN_WARNING "GFS2: Unrecognized block device or " - "mount point %s", dev_name); + "mount point %s\n", dev_name); free_nd: path_release(&nd); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index d0db881..c186857 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -279,7 +279,7 @@ static int bh_get(struct gfs2_quota_data *qd) (bh->b_data + sizeof(struct gfs2_meta_header) + offset * sizeof(struct gfs2_quota_change)); - mutex_lock(&sdp->sd_quota_mutex); + mutex_unlock(&sdp->sd_quota_mutex); return 0; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 70f424f..4fdda97 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -76,7 +76,6 @@ void gfs2_tune_init(struct gfs2_tune *gt) gt->gt_stall_secs = 600; gt->gt_complain_secs = 10; gt->gt_reclaim_limit = 5000; - gt->gt_entries_per_readdir = 32; gt->gt_statfs_quantum = 30; gt->gt_statfs_slow = 0; } diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index e965eb1..9baf697 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -47,7 +47,7 @@ struct dentry_operations hostfs_dentry_ops = { }; /* Changed in hostfs_args before the kernel starts running */ -static char *root_ino = "/"; +static char *root_ino = ""; static int append = 0; #define HOSTFS_SUPER_MAGIC 0x00c0ffee @@ -947,15 +947,17 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) sb->s_magic = HOSTFS_SUPER_MAGIC; sb->s_op = &hostfs_sbops; - if((data == NULL) || (*data == '\0')) - data = root_ino; + /* NULL is printed as <NULL> by sprintf: avoid that. */ + if (data == NULL) + data = ""; err = -ENOMEM; - name = kmalloc(strlen(data) + 1, GFP_KERNEL); + name = kmalloc(strlen(root_ino) + 1 + + strlen(data) + 1, GFP_KERNEL); if(name == NULL) goto out; - strcpy(name, data); + sprintf(name, "%s/%s", root_ino, data); root_inode = iget(sb, 0); if(root_inode == NULL) @@ -966,6 +968,9 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) goto out_put; HOSTFS_I(root_inode)->host_filename = name; + /* Avoid that in the error path, iput(root_inode) frees again name through + * hostfs_destroy_inode! */ + name = NULL; err = -ENOMEM; sb->s_root = d_alloc_root(root_inode); @@ -977,7 +982,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) /* No iput in this case because the dput does that for us */ dput(sb->s_root); sb->s_root = NULL; - goto out_free; + goto out; } return(0); diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 22d38ff..e46d237 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -180,7 +180,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) } if (res > 0) return state; - if (!err) + if (err) /* The partition is unrecognized. So report I/O errors if there were any */ res = err; if (!res) diff --git a/include/asm-avr32/Kbuild b/include/asm-avr32/Kbuild index 8770e73..3136628 100644 --- a/include/asm-avr32/Kbuild +++ b/include/asm-avr32/Kbuild @@ -1,3 +1,3 @@ include include/asm-generic/Kbuild.asm -headers-y += cachectl.h +header-y += cachectl.h diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h index 115813e..21bb60b 100644 --- a/include/asm-avr32/dma-mapping.h +++ b/include/asm-avr32/dma-mapping.h @@ -274,6 +274,24 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); } +static inline void +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + /* just sync everything, that's all the pci API can do */ + dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); +} + +static inline void +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + /* just sync everything, that's all the pci API can do */ + dma_sync_single_for_device(dev, dma_handle, offset+size, direction); +} + /** * dma_sync_sg_for_cpu * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h index e06ef07..833437d 100644 --- a/include/asm-mips/dma.h +++ b/include/asm-mips/dma.h @@ -74,7 +74,7 @@ * */ -#ifndef GENERIC_ISA_DMA_SUPPORT_BROKEN +#ifndef CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN #define MAX_DMA_CHANNELS 8 #endif diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h index e3a180c..9a3cb6b 100644 --- a/include/asm-sh/cache.h +++ b/include/asm-sh/cache.h @@ -21,6 +21,7 @@ #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) +#ifndef __ASSEMBLY__ struct cache_info { unsigned int ways; /* Number of cache ways */ unsigned int sets; /* Number of cache sets */ @@ -47,6 +48,6 @@ struct cache_info { unsigned long flags; }; - +#endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* __ASM_SH_CACHE_H */ diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h index 22f1263..07f62ec 100644 --- a/include/asm-sh/cacheflush.h +++ b/include/asm-sh/cacheflush.h @@ -30,8 +30,5 @@ extern void __flush_invalidate_region(void *start, int size); #define HAVE_ARCH_UNMAPPED_AREA -/* Page flag for lazy dcache write-back for the aliasing UP caches */ -#define PG_dcache_dirty PG_arch_1 - #endif /* __KERNEL__ */ #endif /* __ASM_SH_CACHEFLUSH_H */ diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h index 6fabbba..f70d8ef7 100644 --- a/include/asm-sh/cpu-sh3/cacheflush.h +++ b/include/asm-sh/cpu-sh3/cacheflush.h @@ -36,6 +36,8 @@ /* 32KB cache, 4kb PAGE sizes need to check bit 12 */ #define CACHE_ALIAS 0x00001000 +#define PG_mapped PG_arch_1 + void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); #define flush_cache_dup_mm(mm) flush_cache_mm(mm) diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h index b3746a9..5fd5c89 100644 --- a/include/asm-sh/cpu-sh4/cacheflush.h +++ b/include/asm-sh/cpu-sh4/cacheflush.h @@ -39,4 +39,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, /* Initialization of P3 area for copy_user_page */ void p3_cache_init(void); +#define PG_mapped PG_arch_1 + #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */ diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 9214c01..184d7fc 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -583,6 +583,11 @@ struct mm_struct; extern unsigned int kobjsize(const void *objp); #endif /* !CONFIG_MMU */ +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) +#define __HAVE_ARCH_PTEP_GET_AND_CLEAR +extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +#endif + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init(void); diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index 279e70a..31d55e3 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h @@ -111,6 +111,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */ +#define TIF_SINGLESTEP 5 /* singlestepping active */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 18 @@ -121,6 +122,7 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) +#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_FREEZE (1<<TIF_FREEZE) diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index be9509c..284dfd0 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h @@ -19,6 +19,17 @@ */ #define HAS_DMA +static DEFINE_SPINLOCK(dma_spin_lock); + +#define claim_dma_lock() \ +({ unsigned long flags; \ + spin_lock_irqsave(&dma_spin_lock, flags); \ + flags; \ +}) + +#define release_dma_lock(__flags) \ + spin_unlock_irqrestore(&dma_spin_lock, __flags); + static struct sparc_ebus_info { struct ebus_dma_info info; unsigned int addr; diff --git a/include/linux/compat.h b/include/linux/compat.h index 80b17f4..ccd863d 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -234,5 +234,24 @@ asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, const compat_ulong_t __user *new_nodes); +/* + * epoll (fs/eventpoll.c) compat bits follow ... + */ +#ifndef CONFIG_HAS_COMPAT_EPOLL_EVENT +struct epoll_event; +#define compat_epoll_event epoll_event +#else +asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd, + struct compat_epoll_event __user *event); +asmlinkage long compat_sys_epoll_wait(int epfd, + struct compat_epoll_event __user *events, + int maxevents, int timeout); +#endif +asmlinkage long compat_sys_epoll_pwait(int epfd, + struct compat_epoll_event __user *events, + int maxevents, int timeout, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 92a1fc4..5a00aa8 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -988,8 +988,9 @@ extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_selector *sel, - struct xfrm_sec_ctx *ctx, int delete); -struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete); + struct xfrm_sec_ctx *ctx, int delete, + int *err); +struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 34b2301..1b255df 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -846,7 +846,8 @@ static ctl_table vm_table[] = { .extra2 = &one_hundred, }, #endif -#ifdef CONFIG_X86_32 +#if defined(CONFIG_X86_32) || \ + (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) { .ctl_name = VM_VDSO_ENABLED, .procname = "vdso_enabled", diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f928d2b..71f5cfb 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -656,7 +656,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, /* Detach sockets from device */ read_lock(&hci_sk_list.lock); sk_for_each(sk, node, &hci_sk_list.head) { - bh_lock_sock(sk); + lock_sock(sk); if (hci_pi(sk)->hdev == hdev) { hci_pi(sk)->hdev = NULL; sk->sk_err = EPIPE; @@ -665,7 +665,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, hci_dev_put(hdev); } - bh_unlock_sock(sk); + release_sock(sk); } read_unlock(&hci_sk_list.lock); } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 6845a25..f3a2e29 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -428,6 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); br_features_recompute(br); + + if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && + (br->dev->flags & IFF_UP)) + br_stp_enable_port(p); spin_unlock_bh(&br->lock); dev_set_mtu(br->dev, br_min_mtu(br)); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 5361a4d..746f79d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -545,12 +545,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - case TFRC_SSTATE_NO_SENT: - /* - * XXX when implementing bidirectional rx/tx check this again - */ - DCCP_WARN("Illegal ACK received - no packet sent\n"); - /* fall through */ + case TFRC_SSTATE_NO_SENT: /* fall through */ case TFRC_SSTATE_TERM: /* ignore feedback when closing */ break; } diff --git a/net/dccp/input.c b/net/dccp/input.c index 287099f..78b043c 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -248,18 +248,8 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, DCCP_ACKVEC_STATE_RECEIVED)) goto discard; - /* - * Deliver to the CCID module in charge. - * FIXME: Currently DCCP operates one-directional only, i.e. a listening - * server is not at the same time a connecting client. There is - * not much sense in delivering to both rx/tx sides at the moment - * (only one is active at a time); when moving to bidirectional - * service, this needs to be revised. - */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - else /* listening or connected server */ - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); return __dccp_rcv_established(sk, skb, dh, len); discard: @@ -494,11 +484,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, DCCP_ACKVEC_STATE_RECEIVED)) goto discard; - /* XXX see the comments in dccp_rcv_established about this */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - else - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); } /* diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ce6c460..fc620a7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1215,6 +1215,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen)) goto short_packet; + uh = skb->h.uh; udp4_csum_init(skb, uh); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e16f1bb..a7fee6b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -342,10 +342,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) } #endif - if (netif_carrier_ok(dev)) - ndev->if_flags |= IF_READY; - - ipv6_mc_init_dev(ndev); ndev->tstamp = jiffies; #ifdef CONFIG_SYSCTL diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 286c867..4e0561a 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -795,11 +795,15 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_ipv6_setsockopt); #endif -static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, +static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, char __user *optval, int len) { - if (!hdr) + struct ipv6_opt_hdr *hdr; + + if (!opt || !opt->hopopt) return 0; + hdr = opt->hopopt; + len = min_t(int, len, ipv6_optlen(hdr)); if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) return -EFAULT; @@ -940,7 +944,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, { lock_sock(sk); - len = ipv6_getsockopt_sticky(sk, np->opt->hopopt, + len = ipv6_getsockopt_sticky(sk, np->opt, optval, len); release_sock(sk); return put_user(len, optlen); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 6f19c4a..d110245 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -257,6 +257,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum, } nf_conntrack_get(reasm->nfct); (*pskb)->nfct = reasm->nfct; + (*pskb)->nfctinfo = reasm->nfctinfo; return NF_ACCEPT; } diff --git a/net/key/af_key.c b/net/key/af_key.c index 1c58204..a4e7e2d 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1467,9 +1467,6 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h err = xfrm_state_delete(x); - xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, - AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); - if (err < 0) goto out; @@ -1478,6 +1475,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h c.event = XFRM_MSG_DELSA; km_state_notify(x, &c); out: + xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, + AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); xfrm_state_put(x); return err; @@ -2294,14 +2293,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg } xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1, - &sel, tmp.security, 1); + &sel, tmp.security, 1, &err); security_xfrm_policy_free(&tmp); if (xp == NULL) return -ENOENT; - err = security_xfrm_policy_delete(xp); - xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); @@ -2539,7 +2536,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) { unsigned int dir; - int err; + int err = 0, delete; struct sadb_x_policy *pol; struct xfrm_policy *xp; struct km_event c; @@ -2551,16 +2548,20 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (dir >= XFRM_POLICY_MAX) return -EINVAL; + delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, - hdr->sadb_msg_type == SADB_X_SPDDELETE2); + delete, &err); if (xp == NULL) return -ENOENT; - err = 0; + if (delete) { + xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, + AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); - c.seq = hdr->sadb_msg_seq; - c.pid = hdr->sadb_msg_pid; - if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) { + if (err) + goto out; + c.seq = hdr->sadb_msg_seq; + c.pid = hdr->sadb_msg_pid; c.data.byid = 1; c.event = XFRM_MSG_DELPOLICY; km_policy_notify(xp, dir, &c); @@ -2568,6 +2569,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h err = key_pol_get_resp(sk, xp, hdr, dir); } +out: xfrm_pol_put(xp); return err; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 91a0972..5cb30eb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -486,7 +486,7 @@ __build_packet_message(struct nfulnl_instance *inst, * for physical device (when called from ipv4) */ NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint); - if (skb->nf_bridge) { + if (skb->nf_bridge && skb->nf_bridge->physoutdev) { tmp_uint = htonl(skb->nf_bridge->physoutdev->ifindex); NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, @@ -615,7 +615,7 @@ nfulnl_log_packet(unsigned int pf, plen = 0; if (prefix) - plen = strlen(prefix); + plen = strlen(prefix) + 1; /* all macros expand to constant values at compile time */ /* FIXME: do we want to make the size calculation conditional based on diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 63fe109..0b9c49b 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -360,7 +360,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, return; } - read_lock(&in6_dev->lock); + read_lock_bh(&in6_dev->lock); for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { /* Add the address to the local list. */ addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); @@ -374,7 +374,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, } } - read_unlock(&in6_dev->lock); + read_unlock_bh(&in6_dev->lock); rcu_read_unlock(); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 946b715..0c3a70a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -735,12 +735,14 @@ EXPORT_SYMBOL(xfrm_policy_insert); struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_selector *sel, - struct xfrm_sec_ctx *ctx, int delete) + struct xfrm_sec_ctx *ctx, int delete, + int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; struct hlist_node *entry; + *err = 0; write_lock_bh(&xfrm_policy_lock); chain = policy_hash_bysel(sel, sel->family, dir); ret = NULL; @@ -750,6 +752,11 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, xfrm_sec_ctx_match(ctx, pol->security)) { xfrm_pol_hold(pol); if (delete) { + *err = security_xfrm_policy_delete(pol); + if (*err) { + write_unlock_bh(&xfrm_policy_lock); + return pol; + } hlist_del(&pol->bydst); hlist_del(&pol->byidx); xfrm_policy_count[dir]--; @@ -768,12 +775,14 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); -struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) +struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, + int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; struct hlist_node *entry; + *err = 0; write_lock_bh(&xfrm_policy_lock); chain = xfrm_policy_byidx + idx_hash(id); ret = NULL; @@ -781,6 +790,11 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) if (pol->type == type && pol->index == id) { xfrm_pol_hold(pol); if (delete) { + *err = security_xfrm_policy_delete(pol); + if (*err) { + write_unlock_bh(&xfrm_policy_lock); + return pol; + } hlist_del(&pol->bydst); hlist_del(&pol->byidx); xfrm_policy_count[dir]--; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 956cfe0..9678995 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -530,9 +530,6 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, err = xfrm_state_delete(x); - xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, - AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); - if (err < 0) goto out; @@ -542,6 +539,8 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, km_state_notify(x, &c); out: + xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, + AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); xfrm_state_put(x); return err; } @@ -1254,7 +1253,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, delete); + xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); else { struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; struct xfrm_policy tmp; @@ -1270,7 +1269,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); + xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, + delete, &err); security_xfrm_policy_free(&tmp); } if (xp == NULL) @@ -1288,8 +1288,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, MSG_DONTWAIT); } } else { - err = security_xfrm_policy_delete(xp); - xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); @@ -1303,9 +1301,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, km_policy_notify(xp, p->dir, &c); } - xfrm_pol_put(xp); - out: + xfrm_pol_put(xp); return err; } @@ -1502,7 +1499,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, 0); + xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); else { struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; struct xfrm_policy tmp; @@ -1518,13 +1515,14 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0); + xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, + 0, &err); security_xfrm_policy_free(&tmp); } if (xp == NULL) - return err; - read_lock(&xp->lock); + return -ENOENT; + read_lock(&xp->lock); if (xp->dead) { read_unlock(&xp->lock); goto out; |