Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 14 Feb 2007 00:28:23 +0000 (16:28 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 14 Feb 2007 00:28:23 +0000 (16:28 -0800)
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  i2c: Stop using i2c_adapter.class_dev
  i2c: Remove the warning on missing adapter device
  i2c: Declare more i2c_adapter parent devices
  i2c: PA Semi SMBus driver
  i2c-amd8111: Proposed cleanups
  i2c-parport: Add support for One For All remote JP1 interface
  i2c-viapro: Add support for the VIA CX700 south bridge
  i2c: Add IDs to adapters
  i2c: Update the list of bus IDs
  i2c: Add driver suspend/resume/shutdown support
  i2c: completion header cleanups
  i2c-i801: Document the SMBus unhiding quirk
  i2c-i801: Spelling fix
  i2c: Fix typo in SMBus Write Word Data description
  i2c-piix4: Add support for the ATI SB600
  i2c-nforce2: Drop unused reference to pci_dev
  i2c/vt8231: Remove superfluous initialization
  i2c-ali1563: Fix device initialization
  i2c-ali1563: Improve the status messages

73 files changed:
arch/mips/Kconfig
arch/mips/configs/ip27_defconfig
arch/mips/dec/int-handler.S
arch/mips/kernel/entry.S
arch/mips/kernel/linux32.c
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/signal-common.h
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/mm/Makefile
arch/mips/mm/c-sb1.c
arch/mips/mm/dma-coherent.c [deleted file]
arch/mips/mm/dma-default.c [new file with mode: 0644]
arch/mips/mm/dma-ip27.c [deleted file]
arch/mips/mm/dma-ip32.c [deleted file]
arch/mips/mm/dma-noncoherent.c [deleted file]
arch/mips/pci/Makefile
arch/mips/pci/pci-dac.c [new file with mode: 0644]
drivers/char/keyboard.c
drivers/char/sysrq.c
drivers/char/tty_io.c
drivers/char/vt.c
drivers/char/watchdog/acquirewdt.c
drivers/char/watchdog/advantechwdt.c
drivers/char/watchdog/alim1535_wdt.c
drivers/char/watchdog/alim7101_wdt.c
drivers/char/watchdog/cpu5wdt.c
drivers/char/watchdog/eurotechwdt.c
drivers/char/watchdog/i6300esb.c
drivers/char/watchdog/i8xx_tco.c
drivers/char/watchdog/iTCO_wdt.c
drivers/char/watchdog/ib700wdt.c
drivers/char/watchdog/ibmasr.c
drivers/char/watchdog/indydog.c
drivers/char/watchdog/machzwd.c
drivers/char/watchdog/mixcomwd.c
drivers/char/watchdog/pc87413_wdt.c
drivers/char/watchdog/pcwd.c
drivers/char/watchdog/pcwd_pci.c
drivers/char/watchdog/pcwd_usb.c
drivers/char/watchdog/pnx4008_wdt.c
drivers/char/watchdog/s3c2410_wdt.c
drivers/char/watchdog/sbc60xxwdt.c
drivers/char/watchdog/sbc8360.c
drivers/char/watchdog/sbc_epx_c3.c
drivers/char/watchdog/sc1200wdt.c
drivers/char/watchdog/sc520_wdt.c
drivers/char/watchdog/shwdt.c
drivers/char/watchdog/smsc37b787_wdt.c
drivers/char/watchdog/softdog.c
drivers/char/watchdog/w83627hf_wdt.c
drivers/char/watchdog/w83697hf_wdt.c
drivers/char/watchdog/w83877f_wdt.c
drivers/char/watchdog/w83977f_wdt.c
drivers/char/watchdog/wafer5823wdt.c
drivers/char/watchdog/wdt.c
drivers/char/watchdog/wdt977.c
drivers/char/watchdog/wdt_pci.c
fs/dcache.c
include/asm-mips/atomic.h
include/asm-mips/bitops.h
include/asm-mips/compat-signal.h [new file with mode: 0644]
include/asm-mips/dma-mapping.h
include/asm-mips/mach-generic/dma-coherence.h [new file with mode: 0644]
include/asm-mips/mach-generic/kmalloc.h
include/asm-mips/mach-ip27/dma-coherence.h [new file with mode: 0644]
include/asm-mips/mach-ip32/dma-coherence.h [new file with mode: 0644]
include/asm-mips/mach-jazz/dma-coherence.h [new file with mode: 0644]
include/asm-mips/spinlock.h
include/asm-mips/system.h
include/asm-mips/uaccess.h

index 5fe195a..a92ce6b 100644 (file)
@@ -598,8 +598,6 @@ config SGI_IP32
        select ARC
        select ARC32
        select BOOT_ELF32
-       select OWN_DMA
-       select DMA_IP32
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select R5000_CPU_SCACHE
@@ -883,9 +881,6 @@ config DMA_NONCOHERENT
 config DMA_NEED_PCI_MAP_STATE
        bool
 
-config OWN_DMA
-       bool
-
 config EARLY_PRINTK
        bool
 
index 96090f2..f21186c 100644 (file)
@@ -264,7 +264,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
+CONFIG_MIPS32_N32=y
 CONFIG_BINFMT_ELF32=y
 
 #
index b251ef8..00cecdc 100644 (file)
                 srlv   t3,t1,t2
 
 handle_it:
-               LONG_L  s0, TI_REGS($28)
-               LONG_S  sp, TI_REGS($28)
-               PTR_LA  ra, ret_from_irq
                j       dec_irq_dispatch
                 nop
 
@@ -277,7 +274,6 @@ fpu:
 #endif
 
 spurious:
-               PTR_LA  ra, _ret_from_irq
                j       spurious_interrupt
                 nop
                END(plat_irq_dispatch)
index f10b6a1..0b78fcb 100644 (file)
 #endif
 
 #ifndef CONFIG_PREEMPT
-       .macro  preempt_stop
-       local_irq_disable
-       .endm
 #define resume_kernel  restore_all
+#else
+#define __ret_from_irq ret_from_exception
 #endif
 
        .text
        .align  5
-FEXPORT(ret_from_irq)
-       LONG_S  s0, TI_REGS($28)
-#ifdef CONFIG_PREEMPT
-FEXPORT(ret_from_exception)
-#else
-       b       _ret_from_irq
+#ifndef CONFIG_PREEMPT
 FEXPORT(ret_from_exception)
-       preempt_stop
+       local_irq_disable                       # preempt stop
+       b       __ret_from_irq
 #endif
-FEXPORT(_ret_from_irq)
+FEXPORT(ret_from_irq)
+       LONG_S  s0, TI_REGS($28)
+FEXPORT(__ret_from_irq)
        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
        andi    t0, t0, KU_USER
        beqz    t0, resume_kernel
index ca7ad78..fc4dd6c 100644 (file)
@@ -39,6 +39,7 @@
 #include <net/sock.h>
 #include <net/scm.h>
 
+#include <asm/compat-signal.h>
 #include <asm/ipc.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
@@ -736,3 +737,49 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
        return do_fork(clone_flags, newsp, &regs, 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(&current->saved_sigmask, &sigsaved,
+                               sizeof(sigsaved));
+                       set_thread_flag(TIF_RESTORE_SIGMASK);
+               } else
+                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+       }
+
+       return error;
+}
index e569b84..10e9a18 100644 (file)
@@ -470,4 +470,4 @@ sys_call_table:
        PTR     sys_get_robust_list
        PTR     sys_kexec_load                  /* 5270 */
        PTR     sys_getcpu
-       PTR     sys_epoll_pwait
+       PTR     compat_sys_epoll_pwait
index ee8802b..2ceda46 100644 (file)
@@ -396,4 +396,4 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_get_robust_list
        PTR     compat_sys_kexec_load
        PTR     sys_getcpu
-       PTR     sys_epoll_pwait
+       PTR     compat_sys_epoll_pwait
index 9a8abd6..fdbdbdc 100644 (file)
 #  define DEBUGP(fmt, args...)
 #endif
 
-/*
- * Horribly complicated - with the bloody RM9000 workarounds enabled
- * the signal trampolines is moving to the end of the structure so we can
- * increase the alignment without breaking software compatibility.
- */
-#if ICACHE_REFILLS_WORKAROUND_WAR == 0
-
-struct sigframe {
-       u32 sf_ass[4];          /* argument save space for o32 */
-       u32 sf_code[2];         /* signal trampoline */
-       struct sigcontext sf_sc;
-       sigset_t sf_mask;
-};
-
-#else  /* ICACHE_REFILLS_WORKAROUND_WAR */
-
-struct sigframe {
-       u32 sf_ass[4];                  /* argument save space for o32 */
-       u32 sf_pad[2];
-       struct sigcontext sf_sc;        /* hw context */
-       sigset_t sf_mask;
-       u32 sf_code[8] ____cacheline_aligned;   /* signal trampoline */
-};
-
-#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
-
-/*
- * handle hardware context
- */
-extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
-extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /*
  * Determine which stack to use..
index 54398af..b2e9ab1 100644 (file)
 
 #include "signal-common.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
 #if ICACHE_REFILLS_WORKAROUND_WAR == 0
 
+struct sigframe {
+       u32 sf_ass[4];          /* argument save space for o32 */
+       u32 sf_code[2];         /* signal trampoline */
+       struct sigcontext sf_sc;
+       sigset_t sf_mask;
+};
+
 struct rt_sigframe {
        u32 rs_ass[4];          /* argument save space for o32 */
        u32 rs_code[2];         /* signal trampoline */
@@ -47,6 +57,14 @@ struct rt_sigframe {
 
 #else
 
+struct sigframe {
+       u32 sf_ass[4];                  /* argument save space for o32 */
+       u32 sf_pad[2];
+       struct sigcontext sf_sc;        /* hw context */
+       sigset_t sf_mask;
+       u32 sf_code[8] ____cacheline_aligned;   /* signal trampoline */
+};
+
 struct rt_sigframe {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_pad[2];
index 183fc7e..c28cb21 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/cache.h>
+#include <linux/compat.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -24,6 +25,7 @@
 
 #include <asm/abi.h>
 #include <asm/asm.h>
+#include <asm/compat-signal.h>
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/sim.h>
@@ -104,8 +106,6 @@ typedef struct compat_siginfo {
 #define __NR_O32_rt_sigreturn          4193
 #define __NR_O32_restart_syscall       4253
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* 32-bit compatibility types */
 
 #define _NSIG_BPW32    32
@@ -139,8 +139,20 @@ struct ucontext32 {
        sigset_t32          uc_sigmask;   /* mask last for extensibility */
 };
 
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
 #if ICACHE_REFILLS_WORKAROUND_WAR == 0
 
+struct sigframe32 {
+       u32 sf_ass[4];          /* argument save space for o32 */
+       u32 sf_code[2];         /* signal trampoline */
+       struct sigcontext32 sf_sc;
+       sigset_t sf_mask;
+};
+
 struct rt_sigframe32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_code[2];                 /* signal trampoline */
@@ -150,6 +162,14 @@ struct rt_sigframe32 {
 
 #else  /* ICACHE_REFILLS_WORKAROUND_WAR */
 
+struct sigframe32 {
+       u32 sf_ass[4];                  /* argument save space for o32 */
+       u32 sf_pad[2];
+       struct sigcontext32 sf_sc;      /* hw context */
+       sigset_t sf_mask;
+       u32 sf_code[8] ____cacheline_aligned;   /* signal trampoline */
+};
+
 struct rt_sigframe32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_pad[2];
@@ -493,13 +513,13 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 
 asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-       struct sigframe __user *frame;
+       struct sigframe32 __user *frame;
        sigset_t blocked;
 
-       frame = (struct sigframe __user *) regs.regs[29];
+       frame = (struct sigframe32 __user *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+       if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
                goto badframe;
 
        sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -536,7 +556,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        frame = (struct rt_sigframe32 __user *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+       if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
@@ -581,7 +601,7 @@ badframe:
 int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
        int signr, sigset_t *set)
 {
-       struct sigframe __user *frame;
+       struct sigframe32 __user *frame;
        int err = 0;
 
        frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -591,7 +611,8 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
        err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
 
        err |= setup_sigcontext32(regs, &frame->sf_sc);
-       err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+       err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
+
        if (err)
                goto give_sigsegv;
 
@@ -650,7 +671,7 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
        err |= __put_user(current->sas_ss_size,
                          &frame->rs_uc.uc_stack.ss_size);
        err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
-       err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+       err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
        if (err)
                goto give_sigsegv;
index 57456e6..7ca2a07 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
+#include <asm/compat-signal.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
@@ -47,7 +48,9 @@
 #define __NR_N32_rt_sigreturn          6211
 #define __NR_N32_restart_syscall       6214
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
+extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
+
 
 /* IRIX compatible stack_t  */
 typedef struct sigaltstack32 {
@@ -61,7 +64,7 @@ struct ucontextn32 {
        s32                 uc_link;
        stack32_t           uc_stack;
        struct sigcontext   uc_mcontext;
-       sigset_t            uc_sigmask;   /* mask last for extensibility */
+       compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
 #if ICACHE_REFILLS_WORKAROUND_WAR == 0
@@ -127,7 +130,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+       if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
@@ -193,7 +196,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        err |= __put_user(current->sas_ss_size,
                          &frame->rs_uc.uc_stack.ss_size);
        err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
-       err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+       err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
        if (err)
                goto give_sigsegv;
index 19e41fd..de57273 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
-obj-y                          += cache.o extable.o fault.o init.o pgtable.o \
-                                  tlbex.o tlbex-fault.o
+obj-y                          += cache.o dma-default.o extable.o fault.o \
+                                  init.o pgtable.o tlbex.o tlbex-fault.o
 
 obj-$(CONFIG_32BIT)            += ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)            += pgtable-64.o
@@ -32,14 +32,4 @@ obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE)        += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)  += sc-mips.o
 
-#
-# Choose one DMA coherency model
-#
-ifndef CONFIG_OWN_DMA
-obj-$(CONFIG_DMA_COHERENT)     += dma-coherent.o
-obj-$(CONFIG_DMA_NONCOHERENT)  += dma-noncoherent.o
-endif
-obj-$(CONFIG_DMA_IP27)         += dma-ip27.o
-obj-$(CONFIG_DMA_IP32)         += dma-ip32.o
-
 EXTRA_AFLAGS := $(CFLAGS)
index 3a8afd4..9ea460b 100644 (file)
@@ -259,6 +259,12 @@ static void sb1_flush_cache_data_page(unsigned long addr)
                on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1);
 }
 #else
+
+static void local_sb1_flush_cache_data_page(unsigned long addr)
+{
+       __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
+}
+
 void sb1_flush_cache_data_page(unsigned long)
        __attribute__((alias("local_sb1_flush_cache_data_page")));
 #endif
diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c
deleted file mode 100644 (file)
index 5697c6e..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-       /* ignore region specifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_phys(ret);
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-       __attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       unsigned long addr = (unsigned long) vaddr;
-
-       free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-       enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       return __pa(ptr);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for (i = 0; i < nents; i++, sg++) {
-               sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset;
-       }
-
-       return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-       unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       return page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-            enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-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)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-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)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-       /*
-        * we fall back to GFP_DMA when the mask isn't all 1s,
-        * so we can't guarantee allocations that must be
-        * within a tighter range than GFP_DMA..
-        */
-       if (mask < 0x00ffffff)
-               return 0;
-
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-       struct page *page, unsigned long offset, int direction)
-{
-       return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
new file mode 100644 (file)
index 0000000..4a32e93
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#include <dma-coherence.h>
+
+/*
+ * Warning on the terminology - Linux calls an uncached area coherent;
+ * MIPS terminology calls memory areas with hardware maintained coherency
+ * coherent.
+ */
+
+static inline int cpu_is_noncoherent_r10000(struct device *dev)
+{
+       return !plat_device_is_coherent(dev) &&
+              (current_cpu_data.cputype == CPU_R10000 &&
+              current_cpu_data.cputype == CPU_R12000);
+}
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+       dma_addr_t * dma_handle, gfp_t gfp)
+{
+       void *ret;
+
+       /* ignore region specifiers */
+       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+               gfp |= GFP_DMA;
+       ret = (void *) __get_free_pages(gfp, get_order(size));
+
+       if (ret != NULL) {
+               memset(ret, 0, size);
+               *dma_handle = plat_map_dma_mem(dev, ret, size);
+       }
+
+       return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+       dma_addr_t * dma_handle, gfp_t gfp)
+{
+       void *ret;
+
+       /* ignore region specifiers */
+       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+               gfp |= GFP_DMA;
+       ret = (void *) __get_free_pages(gfp, get_order(size));
+
+       if (ret) {
+               memset(ret, 0, size);
+               *dma_handle = plat_map_dma_mem(dev, ret, size);
+
+               if (!plat_device_is_coherent(dev)) {
+                       dma_cache_wback_inv((unsigned long) ret, size);
+                       ret = UNCAC_ADDR(ret);
+               }
+       }
+
+       return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+       dma_addr_t dma_handle)
+{
+       free_pages((unsigned long) vaddr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+       dma_addr_t dma_handle)
+{
+       unsigned long addr = (unsigned long) vaddr;
+
+       if (!plat_device_is_coherent(dev))
+               addr = CAC_ADDR(addr);
+
+       free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+static inline void __dma_sync(unsigned long addr, size_t size,
+       enum dma_data_direction direction)
+{
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               dma_cache_wback(addr, size);
+               break;
+
+       case DMA_FROM_DEVICE:
+               dma_cache_inv(addr, size);
+               break;
+
+       case DMA_BIDIRECTIONAL:
+               dma_cache_wback_inv(addr, size);
+               break;
+
+       default:
+               BUG();
+       }
+}
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+       enum dma_data_direction direction)
+{
+       unsigned long addr = (unsigned long) ptr;
+
+       if (!plat_device_is_coherent(dev))
+               __dma_sync(addr, size, direction);
+
+       return plat_map_dma_mem(dev, ptr, size);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+       enum dma_data_direction direction)
+{
+       if (cpu_is_noncoherent_r10000(dev))
+               __dma_sync(plat_dma_addr_to_phys(dma_addr) + PAGE_OFFSET, size,
+                          direction);
+
+       plat_unmap_dma_mem(dma_addr);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+       enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(direction == DMA_NONE);
+
+       for (i = 0; i < nents; i++, sg++) {
+               unsigned long addr;
+
+               addr = (unsigned long) page_address(sg->page);
+               if (!plat_device_is_coherent(dev) && addr)
+                       __dma_sync(addr + sg->offset, sg->length, direction);
+               sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
+                                 sg->offset;
+       }
+
+       return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+       unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (!plat_device_is_coherent(dev)) {
+               unsigned long addr;
+
+               addr = (unsigned long) page_address(page) + offset;
+               dma_cache_wback_inv(addr, size);
+       }
+
+       return plat_map_dma_mem_page(dev, page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+       enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) {
+               unsigned long addr;
+
+               addr = plat_dma_addr_to_phys(dma_address);
+               dma_cache_wback_inv(addr, size);
+       }
+
+       plat_unmap_dma_mem(dma_address);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+       enum dma_data_direction direction)
+{
+       unsigned long addr;
+       int i;
+
+       BUG_ON(direction == DMA_NONE);
+
+       for (i = 0; i < nhwentries; i++, sg++) {
+               if (!plat_device_is_coherent(dev) &&
+                   direction != DMA_TO_DEVICE) {
+                       addr = (unsigned long) page_address(sg->page);
+                       if (addr)
+                               __dma_sync(addr + sg->offset, sg->length,
+                                          direction);
+               }
+               plat_unmap_dma_mem(sg->dma_address);
+       }
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+       size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (cpu_is_noncoherent_r10000(dev)) {
+               unsigned long addr;
+
+               addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+               __dma_sync(addr, size, direction);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+       size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (cpu_is_noncoherent_r10000(dev)) {
+               unsigned long addr;
+
+               addr = plat_dma_addr_to_phys(dma_handle);
+               __dma_sync(addr, size, direction);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+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)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (cpu_is_noncoherent_r10000(dev)) {
+               unsigned long addr;
+
+               addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+               __dma_sync(addr + offset, size, direction);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+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)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (cpu_is_noncoherent_r10000(dev)) {
+               unsigned long addr;
+
+               addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+               __dma_sync(addr + offset, size, direction);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+       enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(direction == DMA_NONE);
+
+       /* Make sure that gcc doesn't leave the empty loop body.  */
+       for (i = 0; i < nelems; i++, sg++) {
+               if (!plat_device_is_coherent(dev))
+                       __dma_sync((unsigned long)page_address(sg->page),
+                                  sg->length, direction);
+               plat_unmap_dma_mem(sg->dma_address);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+       enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(direction == DMA_NONE);
+
+       /* Make sure that gcc doesn't leave the empty loop body.  */
+       for (i = 0; i < nelems; i++, sg++) {
+               if (!plat_device_is_coherent(dev))
+                       __dma_sync((unsigned long)page_address(sg->page),
+                                  sg->length, direction);
+               plat_unmap_dma_mem(sg->dma_address);
+       }
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+       return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+       /*
+        * we fall back to GFP_DMA when the mask isn't all 1s,
+        * so we can't guarantee allocations that must be
+        * within a tighter range than GFP_DMA..
+        */
+       if (mask < 0x00ffffff)
+               return 0;
+
+       return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
+{
+       return plat_device_is_coherent(dev);
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+              enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+
+       if (!plat_device_is_coherent(dev))
+               dma_cache_wback_inv((unsigned long)vaddr, size);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c
deleted file mode 100644 (file)
index f088344..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <asm/cache.h>
-#include <asm/pci/bridge.h>
-
-#define pdev_to_baddr(pdev, addr) \
-       (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
-#define dev_to_baddr(dev, addr) \
-       pdev_to_baddr(to_pci_dev(dev), (addr))
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-
-       /* ignore region specifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = dev_to_baddr(dev, virt_to_phys(ret));
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-       __attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       unsigned long addr = (unsigned long) vaddr;
-
-       free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-       enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       return dev_to_baddr(dev, __pa(ptr));
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for (i = 0; i < nents; i++, sg++) {
-               sg->dma_address = (dma_addr_t) dev_to_baddr(dev,
-                       page_to_phys(sg->page) + sg->offset);
-       }
-
-       return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-       unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       return dev_to_baddr(dev, page_to_phys(page) + offset);
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-            enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-               enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
-               enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-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)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-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)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-                enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-       /*
-        * we fall back to GFP_DMA when the mask isn't all 1s,
-        * so we can't guarantee allocations that must be
-        * within a tighter range than GFP_DMA..
-        */
-       if (mask < 0x00ffffff)
-               return 0;
-
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-       struct page *page, unsigned long offset, int direction)
-{
-       dma64_addr_t addr = page_to_phys(page) + offset;
-
-       return (dma64_addr_t) pdev_to_baddr(pdev, addr);
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus);
-
-       return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
deleted file mode 100644 (file)
index b42b6f7..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- * IP32 changes by Ilya.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/ip32/crime.h>
-
-/*
- * Warning on the terminology - Linux calls an uncached area coherent;
- * MIPS terminology calls memory areas with hardware maintained coherency
- * coherent.
- */
-
-/*
- * Few notes.
- * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
- * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for native-endian)
- * 3. All other devices see memory as one big chunk at 0x40000000
- * 4. Non-PCI devices will pass NULL as struct device*
- * Thus we translate differently, depending on device.
- */
-
-#define RAM_OFFSET_MASK        0x3fffffff
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-       /* ignore region specifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               unsigned long addr = virt_to_phys(ret)&RAM_OFFSET_MASK;
-               memset(ret, 0, size);
-               if(dev==NULL)
-                   addr+= CRIME_HI_MEM_BASE;
-               *dma_handle = addr;
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-
-       ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
-       if (ret) {
-               dma_cache_wback_inv((unsigned long) ret, size);
-               ret = UNCAC_ADDR(ret);
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       free_pages((unsigned long) vaddr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       unsigned long addr = (unsigned long) vaddr;
-
-       addr = CAC_ADDR(addr);
-       free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-static inline void __dma_sync(unsigned long addr, size_t size,
-       enum dma_data_direction direction)
-{
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               dma_cache_wback(addr, size);
-               break;
-
-       case DMA_FROM_DEVICE:
-               dma_cache_inv(addr, size);
-               break;
-
-       case DMA_BIDIRECTIONAL:
-               dma_cache_wback_inv(addr, size);
-               break;
-
-       default:
-               BUG();
-       }
-}
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-       enum dma_data_direction direction)
-{
-       unsigned long addr = (unsigned long) ptr;
-
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               dma_cache_wback(addr, size);
-               break;
-
-       case DMA_FROM_DEVICE:
-               dma_cache_inv(addr, size);
-               break;
-
-       case DMA_BIDIRECTIONAL:
-               dma_cache_wback_inv(addr, size);
-               break;
-
-       default:
-               BUG();
-       }
-
-       addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;
-       if(dev == NULL)
-           addr+=CRIME_HI_MEM_BASE;
-       return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-       enum dma_data_direction direction)
-{
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               break;
-
-       case DMA_FROM_DEVICE:
-               break;
-
-       case DMA_BIDIRECTIONAL:
-               break;
-
-       default:
-               BUG();
-       }
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for (i = 0; i < nents; i++, sg++) {
-               unsigned long addr;
-
-               addr = (unsigned long) page_address(sg->page)+sg->offset;
-               if (addr)
-                       __dma_sync(addr, sg->length, direction);
-               addr = __pa(addr)&RAM_OFFSET_MASK;
-               if(dev == NULL)
-                       addr +=  CRIME_HI_MEM_BASE;
-               sg->dma_address = (dma_addr_t)addr;
-       }
-
-       return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-       unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = (unsigned long) page_address(page) + offset;
-       dma_cache_wback_inv(addr, size);
-       addr = __pa(addr)&RAM_OFFSET_MASK;
-       if(dev == NULL)
-               addr +=  CRIME_HI_MEM_BASE;
-
-       return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-       enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       if (direction != DMA_TO_DEVICE) {
-               unsigned long addr;
-
-               dma_address&=RAM_OFFSET_MASK;
-               addr = dma_address + PAGE_OFFSET;
-               if(dma_address>=256*1024*1024)
-                       addr+=CRIME_HI_MEM_BASE;
-               dma_cache_wback_inv(addr, size);
-       }
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-       enum dma_data_direction direction)
-{
-       unsigned long addr;
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       if (direction == DMA_TO_DEVICE)
-               return;
-
-       for (i = 0; i < nhwentries; i++, sg++) {
-               addr = (unsigned long) page_address(sg->page);
-               if (!addr)
-                       continue;
-               dma_cache_wback_inv(addr + sg->offset, sg->length);
-       }
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       dma_handle&=RAM_OFFSET_MASK;
-       addr = dma_handle + PAGE_OFFSET;
-       if(dma_handle>=256*1024*1024)
-           addr+=CRIME_HI_MEM_BASE;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       dma_handle&=RAM_OFFSET_MASK;
-       addr = dma_handle + PAGE_OFFSET;
-       if(dma_handle>=256*1024*1024)
-           addr+=CRIME_HI_MEM_BASE;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-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)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       dma_handle&=RAM_OFFSET_MASK;
-       addr = dma_handle + offset + PAGE_OFFSET;
-       if(dma_handle>=256*1024*1024)
-           addr+=CRIME_HI_MEM_BASE;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-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)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       dma_handle&=RAM_OFFSET_MASK;
-       addr = dma_handle + offset + PAGE_OFFSET;
-       if(dma_handle>=256*1024*1024)
-           addr+=CRIME_HI_MEM_BASE;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++)
-               __dma_sync((unsigned long)page_address(sg->page),
-                          sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++)
-               __dma_sync((unsigned long)page_address(sg->page),
-                          sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-       /*
-        * we fall back to GFP_DMA when the mask isn't all 1s,
-        * so we can't guarantee allocations that must be
-        * within a tighter range than GFP_DMA..
-        */
-       if (mask < 0x00ffffff)
-               return 0;
-
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-       enum dma_data_direction direction)
-{
-       if (direction == DMA_NONE)
-               return;
-
-       dma_cache_wback_inv((unsigned long)vaddr, size);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
deleted file mode 100644 (file)
index 8cecef0..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-/*
- * Warning on the terminology - Linux calls an uncached area coherent;
- * MIPS terminology calls memory areas with hardware maintained coherency
- * coherent.
- */
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-       /* ignore region specifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_phys(ret);
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
-{
-       void *ret;
-
-       ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
-       if (ret) {
-               dma_cache_wback_inv((unsigned long) ret, size);
-               ret = UNCAC_ADDR(ret);
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       free_pages((unsigned long) vaddr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
-{
-       unsigned long addr = (unsigned long) vaddr;
-
-       addr = CAC_ADDR(addr);
-       free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-static inline void __dma_sync(unsigned long addr, size_t size,
-       enum dma_data_direction direction)
-{
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               dma_cache_wback(addr, size);
-               break;
-
-       case DMA_FROM_DEVICE:
-               dma_cache_inv(addr, size);
-               break;
-
-       case DMA_BIDIRECTIONAL:
-               dma_cache_wback_inv(addr, size);
-               break;
-
-       default:
-               BUG();
-       }
-}
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-       enum dma_data_direction direction)
-{
-       unsigned long addr = (unsigned long) ptr;
-
-       __dma_sync(addr, size, direction);
-
-       return virt_to_phys(ptr);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-       enum dma_data_direction direction)
-{
-       unsigned long addr;
-       addr = dma_addr + PAGE_OFFSET;
-
-       //__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for (i = 0; i < nents; i++, sg++) {
-               unsigned long addr;
-
-               addr = (unsigned long) page_address(sg->page);
-               if (addr) {
-                       __dma_sync(addr + sg->offset, sg->length, direction);
-                       sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
-                                         + sg->offset;
-               }
-       }
-
-       return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-       unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = (unsigned long) page_address(page) + offset;
-       dma_cache_wback_inv(addr, size);
-
-       return page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-       enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       if (direction != DMA_TO_DEVICE) {
-               unsigned long addr;
-
-               addr = dma_address + PAGE_OFFSET;
-               dma_cache_wback_inv(addr, size);
-       }
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-       enum dma_data_direction direction)
-{
-       unsigned long addr;
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       if (direction == DMA_TO_DEVICE)
-               return;
-
-       for (i = 0; i < nhwentries; i++, sg++) {
-               addr = (unsigned long) page_address(sg->page);
-               if (addr)
-                       __dma_sync(addr + sg->offset, sg->length, direction);
-       }
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = dma_handle + PAGE_OFFSET;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-       size_t size, enum dma_data_direction direction)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = dma_handle + PAGE_OFFSET;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-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)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = dma_handle + offset + PAGE_OFFSET;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-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)
-{
-       unsigned long addr;
-
-       BUG_ON(direction == DMA_NONE);
-
-       addr = dma_handle + offset + PAGE_OFFSET;
-       __dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++)
-               __dma_sync((unsigned long)page_address(sg->page),
-                          sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-       enum dma_data_direction direction)
-{
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++)
-               __dma_sync((unsigned long)page_address(sg->page),
-                          sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-       /*
-        * we fall back to GFP_DMA when the mask isn't all 1s,
-        * so we can't guarantee allocations that must be
-        * within a tighter range than GFP_DMA..
-        */
-       if (mask < 0x00ffffff)
-               return 0;
-
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-       return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-       enum dma_data_direction direction)
-{
-       if (direction == DMA_NONE)
-               return;
-
-       dma_cache_wback_inv((unsigned long)vaddr, size);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-       struct page *page, unsigned long offset, int direction)
-{
-       return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-       dma64_addr_t dma_addr)
-{
-       return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-       dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-       dma64_addr_t dma_addr, size_t len, int direction)
-{
-       BUG_ON(direction == PCI_DMA_NONE);
-
-       dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
index 82b20c2..bf85995 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
 
-obj-y                          += pci.o
+obj-y                          += pci.o pci-dac.o
 
 #
 # PCI bus host bridge specific code
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
new file mode 100644 (file)
index 0000000..0f0ea1b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#include <dma-coherence.h>
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+       struct page *page, unsigned long offset, int direction)
+{
+       struct device *dev = &pdev->dev;
+
+       BUG_ON(direction == DMA_NONE);
+
+       if (!plat_device_is_coherent(dev)) {
+               unsigned long addr;
+
+               addr = (unsigned long) page_address(page) + offset;
+               dma_cache_wback_inv(addr, PAGE_SIZE);
+       }
+
+       return plat_map_dma_mem_page(dev, page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+       dma64_addr_t dma_addr)
+{
+       return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+       dma64_addr_t dma_addr)
+{
+       return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+       dma64_addr_t dma_addr, size_t len, int direction)
+{
+       BUG_ON(direction == PCI_DMA_NONE);
+
+       if (!plat_device_is_coherent(&pdev->dev))
+               dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+       dma64_addr_t dma_addr, size_t len, int direction)
+{
+       BUG_ON(direction == PCI_DMA_NONE);
+
+       if (!plat_device_is_coherent(&pdev->dev))
+               dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
index c654a3e..cb8d691 100644 (file)
@@ -596,7 +596,6 @@ static void fn_spawn_con(struct vc_data *vc)
 static void fn_SAK(struct vc_data *vc)
 {
        struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
-       PREPARE_WORK(SAK_work, vc_SAK);
        schedule_work(SAK_work);
 }
 
index 3757610..be73c80 100644 (file)
@@ -89,7 +89,6 @@ static struct sysrq_key_op sysrq_loglevel_op = {
 static void sysrq_handle_SAK(int key, struct tty_struct *tty)
 {
        struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
-       PREPARE_WORK(SAK_work, vc_SAK);
        schedule_work(SAK_work);
 }
 static struct sysrq_key_op sysrq_SAK_op = {
index 65672c5..5289254 100644 (file)
@@ -3442,7 +3442,6 @@ void do_SAK(struct tty_struct *tty)
 {
        if (!tty)
                return;
-       PREPARE_WORK(&tty->SAK_work, do_SAK_work);
        schedule_work(&tty->SAK_work);
 }
 
@@ -3568,7 +3567,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
        mutex_init(&tty->atomic_write_lock);
        spin_lock_init(&tty->read_lock);
        INIT_LIST_HEAD(&tty->tty_files);
-       INIT_WORK(&tty->SAK_work, NULL);
+       INIT_WORK(&tty->SAK_work, do_SAK_work);
 }
 
 /*
index 94ce3e7..c3f8e38 100644 (file)
@@ -2635,6 +2635,7 @@ static int __init con_init(void)
         */
        for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
                vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+               INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                visual_init(vc, currcons, 1);
                vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
                vc->vc_kmalloced = 0;
index 154d67e..85269c3 100644 (file)
  *             It can be 1, 2, 10, 20, 110 or 220 seconds.
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
 
+/* Includes */
+#include <linux/module.h>              /* For module specific items */
+#include <linux/moduleparam.h>         /* For new moduleparam's */
+#include <linux/types.h>               /* For standard types (like size_t) */
+#include <linux/errno.h>               /* For the -ENODEV/... values */
+#include <linux/kernel.h>              /* For printk/panic/... */
+#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>            /* For the watchdog specific items */
+#include <linux/fs.h>                  /* For file operations */
+#include <linux/ioport.h>              /* For io-port access */
+#include <linux/platform_device.h>     /* For platform_driver framework */
+#include <linux/init.h>                        /* For __init/__exit/... */
+
+#include <asm/uaccess.h>               /* For copy_to_user/put_user/... */
+#include <asm/io.h>                    /* For inb/outb/... */
+
+/* Module information */
+#define DRV_NAME "acquirewdt"
+#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Acquire WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_HEARTBEAT 0   /* There is no way to see what the correct time-out period is */
 
+/* internal variables */
+static struct platform_device *acq_platform_device;    /* the watchdog platform device */
 static unsigned long acq_is_open;
 static char expect_close;
 
-/*
- *     You must set these - there is no sane way to probe for this board.
- */
-
-static int wdt_stop = 0x43;
+/* module parameters */
+static int wdt_stop = 0x43;    /* You must set this - there is no sane way to probe for this board. */
 module_param(wdt_stop, int, 0);
 MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
 
-static int wdt_start = 0x443;
+static int wdt_start = 0x443;  /* You must set this - there is no sane way to probe for this board. */
 module_param(wdt_start, int, 0);
 MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
- *     Kernel methods.
+ *     Watchdog Operations
  */
 
 static void acq_keepalive(void)
@@ -103,7 +109,7 @@ static void acq_stop(void)
 }
 
 /*
- *     /dev/watchdog handling.
+ *     /dev/watchdog handling
  */
 
 static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
@@ -143,7 +149,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        {
                .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
                .firmware_version = 1,
-               .identity = "Acquire WDT",
+               .identity = WATCHDOG_NAME,
        };
 
        switch(cmd)
@@ -213,20 +219,6 @@ static int acq_close(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- *     Notifier for system down
- */
-
-static int acq_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the WDT off */
-               acq_stop();
-       }
-       return NOTIFY_DONE;
-}
-
 /*
  *     Kernel Interfaces
  */
@@ -240,29 +232,20 @@ static const struct file_operations acq_fops = {
        .release        = acq_close,
 };
 
-static struct miscdevice acq_miscdev=
-{
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &acq_fops,
+static struct miscdevice acq_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &acq_fops,
 };
 
 /*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
+ *     Init & exit routines
  */
 
-static struct notifier_block acq_notifier =
-{
-       .notifier_call = acq_notify_sys,
-};
-
-static int __init acq_init(void)
+static int __devinit acq_probe(struct platform_device *dev)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
-
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
                        printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -279,18 +262,11 @@ static int __init acq_init(void)
                goto unreg_stop;
        }
 
-       ret = register_reboot_notifier(&acq_notifier);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto unreg_regions;
-       }
-
        ret = misc_register(&acq_miscdev);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
                        WATCHDOG_MINOR, ret);
-               goto unreg_reboot;
+               goto unreg_regions;
        }
 
        printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
@@ -298,8 +274,6 @@ static int __init acq_init(void)
 
        return 0;
 
-unreg_reboot:
-       unregister_reboot_notifier(&acq_notifier);
 unreg_regions:
        release_region(wdt_start, 1);
 unreg_stop:
@@ -309,13 +283,60 @@ out:
        return ret;
 }
 
-static void __exit acq_exit(void)
+static int __devexit acq_remove(struct platform_device *dev)
 {
        misc_deregister(&acq_miscdev);
-       unregister_reboot_notifier(&acq_notifier);
+       release_region(wdt_start,1);
        if(wdt_stop != wdt_start)
                release_region(wdt_stop,1);
-       release_region(wdt_start,1);
+
+       return 0;
+}
+
+static void acq_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       acq_stop();
+}
+
+static struct platform_driver acquirewdt_driver = {
+       .probe          = acq_probe,
+       .remove         = __devexit_p(acq_remove),
+       .shutdown       = acq_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init acq_init(void)
+{
+       int err;
+
+       printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
+
+       err = platform_driver_register(&acquirewdt_driver);
+       if (err)
+               return err;
+
+       acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(acq_platform_device)) {
+               err = PTR_ERR(acq_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&acquirewdt_driver);
+       return err;
+}
+
+static void __exit acq_exit(void)
+{
+       platform_device_unregister(acq_platform_device);
+       platform_driver_unregister(&acquirewdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(acq_init);
index 9d73276..8121cc2 100644 (file)
 #include <linux/watchdog.h>
 #include <linux/fs.h>
 #include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
+#include <linux/platform_device.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define DRV_NAME "advantechwdt"
+#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Advantech WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
+static struct platform_device *advwdt_platform_device; /* the watchdog platform device */
 static unsigned long advwdt_is_open;
 static char adv_expect_close;
 
@@ -75,10 +76,10 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, defaul
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
- *     Kernel methods.
+ *     Watchdog Operations
  */
 
 static void
@@ -94,6 +95,20 @@ advwdt_disable(void)
        inb_p(wdt_stop);
 }
 
+static int
+advwdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 63))
+               return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
 static ssize_t
 advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -126,7 +141,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        static struct watchdog_info ident = {
                .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
                .firmware_version = 1,
-               .identity = "Advantech WDT",
+               .identity = WATCHDOG_NAME,
        };
 
        switch (cmd) {
@@ -146,9 +161,8 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case WDIOC_SETTIMEOUT:
          if (get_user(new_timeout, p))
                  return -EFAULT;
-         if ((new_timeout < 1) || (new_timeout > 63))
+         if (advwdt_set_heartbeat(new_timeout))
                  return -EINVAL;
-         timeout = new_timeout;
          advwdt_ping();
          /* Fall */
 
@@ -208,21 +222,6 @@ advwdt_close(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- *     Notifier for system down
- */
-
-static int
-advwdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               advwdt_disable();
-       }
-       return NOTIFY_DONE;
-}
-
 /*
  *     Kernel Interfaces
  */
@@ -237,33 +236,20 @@ static const struct file_operations advwdt_fops = {
 };
 
 static struct miscdevice advwdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &advwdt_fops,
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &advwdt_fops,
 };
 
 /*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
+ *     Init & exit routines
  */
 
-static struct notifier_block advwdt_notifier = {
-       .notifier_call = advwdt_notify_sys,
-};
-
-static int __init
-advwdt_init(void)
+static int __devinit
+advwdt_probe(struct platform_device *dev)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
-
-       if (timeout < 1 || timeout > 63) {
-               timeout = WATCHDOG_TIMEOUT;
-               printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
-                       timeout);
-       }
-
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
                        printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -280,18 +266,18 @@ advwdt_init(void)
                goto unreg_stop;
        }
 
-       ret = register_reboot_notifier(&advwdt_notifier);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto unreg_regions;
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (advwdt_set_heartbeat(timeout)) {
+               advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
+                       timeout);
        }
 
        ret = misc_register(&advwdt_miscdev);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
                        WATCHDOG_MINOR, ret);
-               goto unreg_reboot;
+               goto unreg_regions;
        }
 
        printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
@@ -299,8 +285,6 @@ advwdt_init(void)
 
 out:
        return ret;
-unreg_reboot:
-       unregister_reboot_notifier(&advwdt_notifier);
 unreg_regions:
        release_region(wdt_start, 1);
 unreg_stop:
@@ -309,14 +293,64 @@ unreg_stop:
        goto out;
 }
 
-static void __exit
-advwdt_exit(void)
+static int __devexit
+advwdt_remove(struct platform_device *dev)
 {
        misc_deregister(&advwdt_miscdev);
-       unregister_reboot_notifier(&advwdt_notifier);
+       release_region(wdt_start,1);
        if(wdt_stop != wdt_start)
                release_region(wdt_stop,1);
-       release_region(wdt_start,1);
+
+       return 0;
+}
+
+static void
+advwdt_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       advwdt_disable();
+}
+
+static struct platform_driver advwdt_driver = {
+       .probe          = advwdt_probe,
+       .remove         = __devexit_p(advwdt_remove),
+       .shutdown       = advwdt_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init
+advwdt_init(void)
+{
+       int err;
+
+       printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
+
+       err = platform_driver_register(&advwdt_driver);
+       if (err)
+               return err;
+
+       advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(advwdt_platform_device)) {
+               err = PTR_ERR(advwdt_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&advwdt_driver);
+       return err;
+}
+
+static void __exit
+advwdt_exit(void)
+{
+       platform_device_unregister(advwdt_platform_device);
+       platform_driver_unregister(&advwdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(advwdt_init);
index 01b0d13..e3f6a7d 100644 (file)
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, defaul
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     ali_start       -       start watchdog countdown
index e5b2c2e..67aed9f 100644 (file)
@@ -69,7 +69,7 @@ module_param(use_gpio, int, 0);
 MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog.  (required by old cobalt boards)");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -78,7 +78,7 @@ static struct pci_dev *alim7101_pmu;
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
-                __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")");
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Whack the dog
@@ -108,8 +108,7 @@ static void wdt_timer_ping(unsigned long data)
                printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
        }
        /* Re-set the timer interval */
-       timer.expires = jiffies + WDT_INTERVAL;
-       add_timer(&timer);
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 }
 
 /*
@@ -147,9 +146,7 @@ static void wdt_startup(void)
        wdt_change(WDT_ENABLE);
 
        /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL;
-       add_timer(&timer);
-
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 
        printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
@@ -380,10 +377,6 @@ static int __init alim7101_wdt_init(void)
                        timeout);
        }
 
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 1;
-
        rc = misc_register(&wdt_miscdev);
        if (rc) {
                printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
index 00bdabb..bcd7e36 100644 (file)
@@ -80,10 +80,8 @@ static void cpu5wdt_trigger(unsigned long unused)
        outb(1, port + CPU5WDT_TRIGGER_REG);
 
        /* requeue?? */
-       if( cpu5wdt_device.queue && ticks ) {
-               cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
-               add_timer(&cpu5wdt_device.timer);
-       }
+       if (cpu5wdt_device.queue && ticks)
+               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
        else {
                /* ticks doesn't matter anyway */
                complete(&cpu5wdt_device.stop);
@@ -109,8 +107,7 @@ static void cpu5wdt_start(void)
                outb(1, port + CPU5WDT_MODE_REG);
                outb(0, port + CPU5WDT_RESET_REG);
                outb(0, port + CPU5WDT_ENABLE_REG);
-               cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
-               add_timer(&cpu5wdt_device.timer);
+               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
        }
        /* if process dies, counter is not decremented */
        cpu5wdt_device.running++;
@@ -245,9 +242,7 @@ static int __devinit cpu5wdt_init(void)
 
        clear_bit(0, &cpu5wdt_device.inuse);
 
-       init_timer(&cpu5wdt_device.timer);
-       cpu5wdt_device.timer.function = cpu5wdt_trigger;
-       cpu5wdt_device.timer.data = 0;
+       setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
 
        cpu5wdt_device.default_ticks = ticks;
 
index e228d6e..f70387f 100644 (file)
@@ -73,7 +73,7 @@ static char *ev = "int";
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some symbolic names
index fb64df4..c598250 100644 (file)
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, d
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some i6300ESB specific functions
index e0627d7..a62ef48 100644 (file)
@@ -109,7 +109,7 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, def
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some TCO specific functions
index fd8a44a..3c9684c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
  *
- *     (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2006-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -49,7 +49,7 @@
 /* Module and version information */
 #define DRV_NAME        "iTCO_wdt"
 #define DRV_VERSION     "1.01"
-#define DRV_RELDATE     "11-Nov-2006"
+#define DRV_RELDATE     "21-Jan-2007"
 #define PFX            DRV_NAME ": "
 
 /* Includes */
@@ -187,7 +187,7 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* iTCO Vendor Specific Support hooks */
 #ifdef CONFIG_ITCO_VENDOR_SUPPORT
index c1ed209..c3a60f5 100644 (file)
@@ -3,8 +3,8 @@
  *
  *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
  *
- *      Based on advantechwdt.c which is based on acquirewdt.c which
- *       is based on wdt.c.
+ *     Based on advantechwdt.c which is based on acquirewdt.c which
+ *     is based on wdt.c.
  *
  *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
  *
@@ -25,9 +25,9 @@
  *
  *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
- *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *           Added timeout module option to override default
+ *     14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  *
  */
 
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/ioport.h>
-#include <linux/notifier.h>
 #include <linux/fs.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/moduleparam.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+static struct platform_device *ibwdt_platform_device;
 static unsigned long ibwdt_is_open;
 static spinlock_t ibwdt_lock;
 static char expect_close;
 
-#define PFX "ib700wdt: "
+/* Module information */
+#define DRV_NAME "ib700wdt"
+#define PFX DRV_NAME ": "
 
 /*
  *
@@ -118,20 +120,51 @@ static int wd_margin = WD_TIMO;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 
 /*
- *     Kernel methods.
+ *     Watchdog Operations
  */
 
 static void
 ibwdt_ping(void)
 {
+       spin_lock(&ibwdt_lock);
+
        /* Write a watchdog value */
        outb_p(wd_margin, WDT_START);
+
+       spin_unlock(&ibwdt_lock);
 }
 
+static void
+ibwdt_disable(void)
+{
+       spin_lock(&ibwdt_lock);
+       outb_p(0, WDT_STOP);
+       spin_unlock(&ibwdt_lock);
+}
+
+static int
+ibwdt_set_heartbeat(int t)
+{
+       int i;
+
+       if ((t < 0) || (t > 30))
+               return -EINVAL;
+
+       for (i = 0x0F; i > -1; i--)
+               if (wd_times[i] > t)
+                       break;
+       wd_margin = i;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
 static ssize_t
 ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -159,7 +192,7 @@ static int
 ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
          unsigned long arg)
 {
-       int i, new_margin;
+       int new_margin;
        void __user *argp = (void __user *)arg;
        int __user *p = argp;
 
@@ -176,6 +209,7 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
          break;
 
        case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
          return put_user(0, p);
 
        case WDIOC_KEEPALIVE:
@@ -185,18 +219,33 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case WDIOC_SETTIMEOUT:
          if (get_user(new_margin, p))
                  return -EFAULT;
-         if ((new_margin < 0) || (new_margin > 30))
+         if (ibwdt_set_heartbeat(new_margin))
                  return -EINVAL;
-         for (i = 0x0F; i > -1; i--)
-                 if (wd_times[i] > new_margin)
-                         break;
-         wd_margin = i;
          ibwdt_ping();
          /* Fall */
 
        case WDIOC_GETTIMEOUT:
          return put_user(wd_times[wd_margin], p);
-         break;
+
+       case WDIOC_SETOPTIONS:
+       {
+         int options, retval = -EINVAL;
+
+         if (get_user(options, p))
+           return -EFAULT;
+
+         if (options & WDIOS_DISABLECARD) {
+           ibwdt_disable();
+           retval = 0;
+         }
+
+         if (options & WDIOS_ENABLECARD) {
+           ibwdt_ping();
+           retval = 0;
+         }
+
+         return retval;
+       }
 
        default:
          return -ENOTTY;
@@ -207,9 +256,7 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 static int
 ibwdt_open(struct inode *inode, struct file *file)
 {
-       spin_lock(&ibwdt_lock);
        if (test_and_set_bit(0, &ibwdt_is_open)) {
-               spin_unlock(&ibwdt_lock);
                return -EBUSY;
        }
        if (nowayout)
@@ -217,40 +264,23 @@ ibwdt_open(struct inode *inode, struct file *file)
 
        /* Activate */
        ibwdt_ping();
-       spin_unlock(&ibwdt_lock);
        return nonseekable_open(inode, file);
 }
 
 static int
 ibwdt_close(struct inode *inode, struct file *file)
 {
-       spin_lock(&ibwdt_lock);
-       if (expect_close == 42)
-               outb_p(0, WDT_STOP);
-       else
+       if (expect_close == 42) {
+               ibwdt_disable();
+       } else {
                printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-
+               ibwdt_ping();
+       }
        clear_bit(0, &ibwdt_is_open);
        expect_close = 0;
-       spin_unlock(&ibwdt_lock);
        return 0;
 }
 
-/*
- *     Notifier for system down
- */
-
-static int
-ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               outb_p(0, WDT_STOP);
-       }
-       return NOTIFY_DONE;
-}
-
 /*
  *     Kernel Interfaces
  */
@@ -271,26 +301,14 @@ static struct miscdevice ibwdt_miscdev = {
 };
 
 /*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
+ *     Init & exit routines
  */
 
-static struct notifier_block ibwdt_notifier = {
-       .notifier_call = ibwdt_notify_sys,
-};
-
-static int __init ibwdt_init(void)
+static int __devinit ibwdt_probe(struct platform_device *dev)
 {
        int res;
 
-       printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
-
        spin_lock_init(&ibwdt_lock);
-       res = misc_register(&ibwdt_miscdev);
-       if (res) {
-               printk (KERN_ERR PFX "failed to register misc device\n");
-               goto out_nomisc;
-       }
 
 #if WDT_START != WDT_STOP
        if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
@@ -305,34 +323,78 @@ static int __init ibwdt_init(void)
                res = -EIO;
                goto out_nostartreg;
        }
-       res = register_reboot_notifier(&ibwdt_notifier);
+
+       res = misc_register(&ibwdt_miscdev);
        if (res) {
-               printk (KERN_ERR PFX "Failed to register reboot notifier.\n");
-               goto out_noreboot;
+               printk (KERN_ERR PFX "failed to register misc device\n");
+               goto out_nomisc;
        }
        return 0;
 
-out_noreboot:
+out_nomisc:
        release_region(WDT_START, 1);
 out_nostartreg:
 #if WDT_START != WDT_STOP
        release_region(WDT_STOP, 1);
 #endif
 out_nostopreg:
-       misc_deregister(&ibwdt_miscdev);
-out_nomisc:
        return res;
 }
 
-static void __exit
-ibwdt_exit(void)
+static int __devexit ibwdt_remove(struct platform_device *dev)
 {
        misc_deregister(&ibwdt_miscdev);
-       unregister_reboot_notifier(&ibwdt_notifier);
+       release_region(WDT_START,1);
 #if WDT_START != WDT_STOP
        release_region(WDT_STOP,1);
 #endif
-       release_region(WDT_START,1);
+       return 0;
+}
+
+static void ibwdt_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       ibwdt_disable();
+}
+
+static struct platform_driver ibwdt_driver = {
+       .probe          = ibwdt_probe,
+       .remove         = __devexit_p(ibwdt_remove),
+       .shutdown       = ibwdt_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init ibwdt_init(void)
+{
+       int err;
+
+       printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
+
+       err = platform_driver_register(&ibwdt_driver);
+       if (err)
+               return err;
+
+       ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(ibwdt_platform_device)) {
+               err = PTR_ERR(ibwdt_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&ibwdt_driver);
+       return err;
+}
+
+static void __exit ibwdt_exit(void)
+{
+       platform_device_unregister(ibwdt_platform_device);
+       platform_driver_unregister(&ibwdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(ibwdt_init);
index dd6760f..8195f50 100644 (file)
@@ -396,7 +396,7 @@ module_init(ibmasr_init);
 module_exit(ibmasr_exit);
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
 MODULE_AUTHOR("Andrey Panin");
index 0bc2393..788245b 100644 (file)
@@ -32,7 +32,7 @@ static int indydog_alive;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void indydog_start(void)
 {
index 4d730fd..81fb3de 100644 (file)
@@ -95,7 +95,7 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #define PFX "machzwd"
 
@@ -118,12 +118,14 @@ static int action = 0;
 module_param(action, int, 0);
 MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
 
+static void zf_ping(unsigned long data);
+
 static int zf_action = GEN_RESET;
 static unsigned long zf_is_open;
 static char zf_expect_close;
 static spinlock_t zf_lock;
 static spinlock_t zf_port_lock;
-static struct timer_list zf_timer;
+static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
 static unsigned long next_heartbeat = 0;
 
 
@@ -220,9 +222,7 @@ static void zf_timer_on(void)
        next_heartbeat = jiffies + ZF_USER_TIMEO;
 
        /* start the timer for internal ping */
-       zf_timer.expires = jiffies + ZF_HW_TIMEO;
-
-       add_timer(&zf_timer);
+       mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
 
        /* start watchdog timer */
        ctrl_reg = zf_get_control();
@@ -260,8 +260,7 @@ static void zf_ping(unsigned long data)
                zf_set_control(ctrl_reg);
                spin_unlock_irqrestore(&zf_port_lock, flags);
 
-               zf_timer.expires = jiffies + ZF_HW_TIMEO;
-               add_timer(&zf_timer);
+               mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
        }else{
                printk(KERN_CRIT PFX ": I will reset your machine\n");
        }
@@ -465,11 +464,6 @@ static int __init zf_init(void)
        zf_set_status(0);
        zf_set_control(0);
 
-       /* this is the timer that will do the hard work */
-       init_timer(&zf_timer);
-       zf_timer.function = zf_ping;
-       zf_timer.data = 0;
-
        return 0;
 
 no_reboot:
index c2dac0a..f35e284 100644 (file)
@@ -56,16 +56,18 @@ static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
 #define FLASHCOM_WATCHDOG_OFFSET 0x4
 #define FLASHCOM_ID 0x18
 
+static void mixcomwd_timerfun(unsigned long d);
+
 static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
 static int mixcomwd_timer_alive;
-static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0);
+static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
 static char expect_close;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void mixcomwd_ping(void)
 {
@@ -77,7 +79,7 @@ static void mixcomwd_timerfun(unsigned long d)
 {
        mixcomwd_ping();
 
-       mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
+       mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
 }
 
 /*
@@ -114,12 +116,8 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
                        printk(KERN_ERR "mixcomwd: release called while internal timer alive");
                        return -EBUSY;
                }
-               init_timer(&mixcomwd_timer);
-               mixcomwd_timer.expires=jiffies + 5 * HZ;
-               mixcomwd_timer.function=mixcomwd_timerfun;
-               mixcomwd_timer.data=0;
                mixcomwd_timer_alive=1;
-               add_timer(&mixcomwd_timer);
+               mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
        } else {
                printk(KERN_CRIT "mixcomwd: WDT device closed unexpectedly.  WDT will not stop!\n");
        }
@@ -285,7 +283,7 @@ static void __exit mixcomwd_exit(void)
                if(mixcomwd_timer_alive) {
                        printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
                               " probably reboot!\n");
-                       del_timer(&mixcomwd_timer);
+                       del_timer_sync(&mixcomwd_timer);
                        mixcomwd_timer_alive=0;
                }
        }
index a77a907..3d3deae 100644 (file)
@@ -631,5 +631,5 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ").");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 8e1e6e4..6e8b570 100644 (file)
@@ -2,7 +2,7 @@
  * PC Watchdog Driver
  * by Ken Hollis (khollis@bitgate.com)
  *
- * Permission granted from Simon Machell (73244.1270@compuserve.com)
+ * Permission granted from Simon Machell (smachell@berkprod.com)
  * Written for the Linux Kernel, and GPLed by Ken Hollis
  *
  * 960107      Added request_region routines, modulized the whole thing.
@@ -70,8 +70,8 @@
 #include <asm/io.h>            /* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.17"
-#define WATCHDOG_DATE "12 Feb 2006"
+#define WATCHDOG_VERSION "1.18"
+#define WATCHDOG_DATE "21 Jan 2007"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
 #define PFX WATCHDOG_NAME ": "
 #define CMD_ISA_DELAY_TIME_8SECS       0x0C
 #define CMD_ISA_RESET_RELAYS           0x0D
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       20,     /* OFF-OFF-OFF  = 20 Sec  */
+       40,     /* OFF-OFF-ON   = 40 Sec  */
+       60,     /* OFF-ON-OFF   =  1 Min  */
+       300,    /* OFF-ON-ON    =  5 Min  */
+       600,    /* ON-OFF-OFF   = 10 Min  */
+       1800,   /* ON-OFF-ON    = 30 Min  */
+       3600,   /* ON-ON-OFF    =  1 Hour */
+       7200,   /* ON-ON-ON     =  2 hour */
+};
+
 /*
  * We are using an kernel timer to do the pinging of the watchdog
  * every ~500ms. We try to set the internal heartbeat of the
@@ -167,14 +179,14 @@ static int debug = QUIET;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
 
-#define WATCHDOG_HEARTBEAT 60          /* 60 sec default heartbeat */
+#define WATCHDOG_HEARTBEAT 0           /* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Internal functions
@@ -831,9 +843,7 @@ static int __devinit pcwatchdog_init(int base_addr)
        /* clear the "card caused reboot" flag */
        pcwd_clear_status();
 
-       init_timer(&pcwd_private.timer);
-       pcwd_private.timer.function = pcwd_timer_ping;
-       pcwd_private.timer.data = 0;
+       setup_timer(&pcwd_private.timer, pcwd_timer_ping, 0);
 
        /*  Disable the board  */
        pcwd_stop();
@@ -844,6 +854,10 @@ static int __devinit pcwatchdog_init(int base_addr)
        /* Show info about the card itself */
        pcwd_show_card_info();
 
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];
+
        /* Check that the heartbeat value is within it's range ; if not reset to the default */
        if (pcwd_set_heartbeat(heartbeat)) {
                pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
index f4872c8..61a89e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Berkshire PCI-PC Watchdog Card Driver
  *
- *     (c) Copyright 2003-2005 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2003-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     Based on source code of the following authors:
  *       Ken Hollis <kenji@bitgate.com>,
@@ -51,8 +51,8 @@
 #include <asm/io.h>            /* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.02"
-#define WATCHDOG_DATE "03 Sep 2005"
+#define WATCHDOG_VERSION "1.03"
+#define WATCHDOG_DATE "21 Jan 2007"
 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
 #define WATCHDOG_NAME "pcwd_pci"
 #define PFX WATCHDOG_NAME ": "
 #define CMD_WRITE_WATCHDOG_TIMEOUT             0x19
 #define CMD_GET_CLEAR_RESET_COUNT              0x84
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       5,      /* OFF-OFF-OFF  =  5 Sec  */
+       10,     /* OFF-OFF-ON   = 10 Sec  */
+       30,     /* OFF-ON-OFF   = 30 Sec  */
+       60,     /* OFF-ON-ON    =  1 Min  */
+       300,    /* ON-OFF-OFF   =  5 Min  */
+       600,    /* ON-OFF-ON    = 10 Min  */
+       1800,   /* ON-ON-OFF    = 30 Min  */
+       3600,   /* ON-ON-ON     =  1 hour */
+};
+
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int cards_found;
 
@@ -119,14 +131,14 @@ static int debug = QUIET;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
 
-#define WATCHDOG_HEARTBEAT 2   /* 2 sec default heartbeat */
+#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Internal functions
@@ -286,7 +298,9 @@ static int pcipcwd_stop(void)
 static int pcipcwd_keepalive(void)
 {
        /* Re-trigger watchdog by writing to port 0 */
+       spin_lock(&pcipcwd_private.io_lock);
        outb_p(0x42, pcipcwd_private.io_addr);  /* send out any data */
+       spin_unlock(&pcipcwd_private.io_lock);
 
        if (debug >= DEBUG)
                printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
@@ -373,7 +387,9 @@ static int pcipcwd_get_temperature(int *temperature)
        if (!pcipcwd_private.supports_temp)
                return -ENODEV;
 
+       spin_lock(&pcipcwd_private.io_lock);
        *temperature = inb_p(pcipcwd_private.io_addr);
+       spin_unlock(&pcipcwd_private.io_lock);
 
        /*
         * Convert celsius to fahrenheit, since this was
@@ -711,6 +727,10 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
        /* Show info about the card itself */
        pcipcwd_show_card_info();
 
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)];
+
        /* Check that the heartbeat value is within it's range ; if not reset to the default */
        if (pcipcwd_set_heartbeat(heartbeat)) {
                pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
@@ -798,6 +818,8 @@ static int __init pcipcwd_init_module(void)
 static void __exit pcipcwd_cleanup_module(void)
 {
        pci_unregister_driver(&pcipcwd_driver);
+
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(pcipcwd_init_module);
index 2da5ac9..31037f9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Berkshire USB-PC Watchdog Card Driver
  *
- *     (c) Copyright 2004 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     Based on source code of the following authors:
  *       Ken Hollis <kenji@bitgate.com>,
  *     http://www.berkprod.com/ or http://www.pcwatchdog.com/
  */
 
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
+#include <linux/module.h>      /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h>       /* For standard types (like size_t) */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/delay.h>       /* For mdelay function */
+#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>    /* For the watchdog specific items */
+#include <linux/notifier.h>    /* For notifier support */
+#include <linux/reboot.h>      /* For reboot_notifier stuff */
+#include <linux/init.h>                /* For __init/__exit/... */
+#include <linux/fs.h>          /* For file operations */
+#include <linux/usb.h>         /* For USB functions */
+#include <linux/slab.h>                /* For kmalloc, ... */
+#include <linux/mutex.h>       /* For mutex locking */
 #include <linux/hid.h>         /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
 
+#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
+
 
 #ifdef CONFIG_USB_DEBUG
        static int debug = 1;
@@ -57,8 +56,8 @@
 
 
 /* Module and Version Information */
-#define DRIVER_VERSION "1.01"
-#define DRIVER_DATE "15 Mar 2005"
+#define DRIVER_VERSION "1.02"
+#define DRIVER_DATE "21 Jan 2007"
 #define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
 #define DRIVER_LICENSE "GPL"
@@ -75,14 +74,14 @@ MODULE_ALIAS_MISCDEV(TEMP_MINOR);
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-#define WATCHDOG_HEARTBEAT 2   /* 2 sec default heartbeat */
+#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* The vendor and product id's for the USB-PC Watchdog card */
 #define USB_PCWD_VENDOR_ID     0x0c98
@@ -110,6 +109,18 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
 #define CMD_ENABLE_WATCHDOG            0x30    /* Enable / Disable Watchdog */
 #define CMD_DISABLE_WATCHDOG           CMD_ENABLE_WATCHDOG
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       5,      /* OFF-OFF-OFF  =  5 Sec  */
+       10,     /* OFF-OFF-ON   = 10 Sec  */
+       30,     /* OFF-ON-OFF   = 30 Sec  */
+       60,     /* OFF-ON-ON    =  1 Min  */
+       300,    /* ON-OFF-OFF   =  5 Min  */
+       600,    /* ON-OFF-ON    = 10 Min  */
+       1800,   /* ON-ON-OFF    = 30 Min  */
+       3600,   /* ON-ON-ON     =  1 hour */
+};
+
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int cards_found;
 
@@ -682,6 +693,10 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
                ((option_switches & 0x10) ? "ON" : "OFF"),
                ((option_switches & 0x08) ? "ON" : "OFF"));
 
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(option_switches & 0x07)];
+
        /* Check that the heartbeat value is within it's range ; if not reset to the default */
        if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
                usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
index ff6f1ca..5991add 100644 (file)
@@ -283,7 +283,8 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
        wdt_base = (void __iomem *)IO_ADDRESS(res->start);
 
        wdt_clk = clk_get(&pdev->dev, "wdt_ck");
-       if (!wdt_clk) {
+       if (IS_ERR(wdt_clk)) {
+               ret = PTR_ERR(wdt_clk);
                release_resource(wdt_mem);
                kfree(wdt_mem);
                goto out;
index 18cb050..dff6cb5 100644 (file)
@@ -78,7 +78,7 @@ MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE
 
 MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
 
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
 
@@ -366,13 +366,15 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
        wdt_mem = request_mem_region(res->start, size, pdev->name);
        if (wdt_mem == NULL) {
                printk(KERN_INFO PFX "failed to get memory region\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto err_req;
        }
 
        wdt_base = ioremap(res->start, size);
        if (wdt_base == 0) {
                printk(KERN_INFO PFX "failed to ioremap() region\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_req;
        }
 
        DBG("probe: mapped wdt_base=%p\n", wdt_base);
@@ -380,22 +382,21 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res == NULL) {
                printk(KERN_INFO PFX "failed to get irq resource\n");
-               iounmap(wdt_base);
-               return -ENOENT;
+               ret = -ENOENT;
+               goto err_map;
        }
 
        ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev);
        if (ret != 0) {
                printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
-               iounmap(wdt_base);
-               return ret;
+               goto err_map;
        }
 
        wdt_clock = clk_get(&pdev->dev, "watchdog");
-       if (wdt_clock == NULL) {
+       if (IS_ERR(wdt_clock)) {
                printk(KERN_INFO PFX "failed to find watchdog clock source\n");
-               iounmap(wdt_base);
-               return -ENOENT;
+               ret = PTR_ERR(wdt_clock);
+               goto err_irq;
        }
 
        clk_enable(wdt_clock);
@@ -418,8 +419,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
        if (ret) {
                printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n",
                        WATCHDOG_MINOR, ret);
-               iounmap(wdt_base);
-               return ret;
+               goto err_clk;
        }
 
        if (tmr_atboot && started == 0) {
@@ -434,26 +434,36 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
        }
 
        return 0;
+
+ err_clk:
+       clk_disable(wdt_clock);
+       clk_put(wdt_clock);
+
+ err_irq:
+       free_irq(wdt_irq->start, pdev);
+
+ err_map:
+       iounmap(wdt_base);
+
+ err_req:
+       release_resource(wdt_mem);
+       kfree(wdt_mem);
+
+       return ret;
 }
 
 static int s3c2410wdt_remove(struct platform_device *dev)
 {
-       if (wdt_mem != NULL) {
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
-               wdt_mem = NULL;
-       }
+       release_resource(wdt_mem);
+       kfree(wdt_mem);
+       wdt_mem = NULL;
 
-       if (wdt_irq != NULL) {
-               free_irq(wdt_irq->start, dev);
-               wdt_irq = NULL;
-       }
+       free_irq(wdt_irq->start, dev);
+       wdt_irq = NULL;
 
-       if (wdt_clock != NULL) {
-               clk_disable(wdt_clock);
-               clk_put(wdt_clock);
-               wdt_clock = NULL;
-       }
+       clk_disable(wdt_clock);
+       clk_put(wdt_clock);
+       wdt_clock = NULL;
 
        iounmap(wdt_base);
        misc_deregister(&s3c2410wdt_miscdev);
index c7b2045..b628203 100644 (file)
@@ -100,10 +100,10 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, defau
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -122,8 +122,7 @@ static void wdt_timer_ping(unsigned long data)
                /* Ping the WDT by reading from wdt_start */
                inb_p(wdt_start);
                /* Re-set the timer interval */
-               timer.expires = jiffies + WDT_INTERVAL;
-               add_timer(&timer);
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else {
                printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
        }
@@ -138,8 +137,7 @@ static void wdt_startup(void)
        next_heartbeat = jiffies + (timeout * HZ);
 
        /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL;
-       add_timer(&timer);
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
        printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
 
@@ -363,10 +361,6 @@ static int __init sbc60xxwdt_init(void)
                }
        }
 
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 0;
-
        rc = misc_register(&wdt_miscdev);
        if (rc)
        {
index 41fc6f8..67ae426 100644 (file)
@@ -204,7 +204,7 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout,
-                "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+                "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Kernel methods.
index 8882b42..82cbd88 100644 (file)
@@ -35,7 +35,7 @@ static int epx_c3_alive;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
 #define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
index e323983..1e4a8d7 100644 (file)
@@ -92,7 +92,7 @@ MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 
 
index caec37b..2676a43 100644 (file)
@@ -97,7 +97,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, defau
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * AMD Elan SC520 - Watchdog Timer Registers
@@ -121,7 +121,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
 static __u16 __iomem *wdtmrctl;
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -145,8 +145,7 @@ static void wdt_timer_ping(unsigned long data)
                spin_unlock(&wdt_spinlock);
 
                /* Re-set the timer interval */
-               timer.expires = jiffies + WDT_INTERVAL;
-               add_timer(&timer);
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else {
                printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
        }
@@ -179,8 +178,7 @@ static int wdt_startup(void)
        next_heartbeat = jiffies + (timeout * HZ);
 
        /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL;
-       add_timer(&timer);
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 
        /* Start the watchdog */
        wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
@@ -389,10 +387,6 @@ static int __init sc520_wdt_init(void)
 
        spin_lock_init(&wdt_spinlock);
 
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 0;
-
        /* Check that the timeout value is within it's range ; if not reset to the default */
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
index dc40362..cecbedd 100644 (file)
@@ -65,10 +65,12 @@ static int clock_division_ratio = WTCSR_CKS_4096;
 
 #define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
 
+static void sh_wdt_ping(unsigned long data);
+
 static unsigned long shwdt_is_open;
 static struct watchdog_info sh_wdt_info;
 static char shwdt_expect_close;
-static struct timer_list timer;
+static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
 static unsigned long next_heartbeat;
 
 #define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
@@ -433,10 +435,6 @@ static int __init sh_wdt_init(void)
                       "be 1<=x<=3600, using %d\n", heartbeat);
        }
 
-       init_timer(&timer);
-       timer.function = sh_wdt_ping;
-       timer.data = 0;
-
        rc = register_reboot_notifier(&sh_wdt_notifier);
        if (unlikely(rc)) {
                printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
index a9681d5..d3cb0a7 100644 (file)
@@ -624,4 +624,4 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 4067e1f..9c36949 100644 (file)
@@ -59,7 +59,7 @@ MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<6
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #ifdef ONLY_TESTING
 static int soft_noboot = 1;
index 07d4bff..337ee42 100644 (file)
@@ -58,7 +58,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, defaul
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Kernel methods.
index c960ec1..d9e821d 100644 (file)
@@ -60,7 +60,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, defau
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *     Kernel methods.
index b0e5f84..3c88fe1 100644 (file)
@@ -87,10 +87,10 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, defau
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -114,8 +114,7 @@ static void wdt_timer_ping(unsigned long data)
                inb_p(WDT_PING);
 
                /* Re-set the timer interval */
-               timer.expires = jiffies + WDT_INTERVAL;
-               add_timer(&timer);
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
 
                spin_unlock(&wdt_spinlock);
 
@@ -155,8 +154,7 @@ static void wdt_startup(void)
        next_heartbeat = jiffies + (timeout * HZ);
 
        /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL;
-       add_timer(&timer);
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 
        wdt_change(WDT_ENABLE);
 
@@ -377,10 +375,6 @@ static int __init w83877f_wdt_init(void)
                goto err_out_region1;
        }
 
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 0;
-
        rc = misc_register(&wdt_miscdev);
        if (rc)
        {
index 2c8d5d8..1579684 100644 (file)
@@ -59,7 +59,7 @@ MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Start the watchdog
index 163e028..950905d 100644 (file)
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, defau
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wafwdt_ping(void)
 {
index 517fbd8..0a3de6a 100644 (file)
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536,
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* You must set these - there is no sane way to probe for this board. */
 static int io=0x240;
index 6253041..7d300ff 100644 (file)
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Start the watchdog
index ce1261c..6baf4ae 100644 (file)
@@ -90,7 +90,7 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536,
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #ifdef CONFIG_WDT_501_PCI
 /* Support for the Fan Tachometer on the PCI-WDT501 */
index b5f6139..d68631f 100644 (file)
@@ -1739,41 +1739,45 @@ shouldnt_be_hashed:
  * @rootmnt: vfsmnt to which the root dentry belongs
  * @buffer: buffer to return value in
  * @buflen: buffer length
- * @fail_deleted: what to return for deleted files
  *
- * Convert a dentry into an ASCII path name. If the entry has been deleted,
- * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
- * the the string " (deleted)" is appended. Note that this is ambiguous.
+ * Convert a dentry into an ASCII path name. If the entry has been deleted
+ * the string " (deleted)" is appended. Note that this is ambiguous.
  *
- * Returns the buffer or an error code.
+ * Returns the buffer or an error code if the path was too long.
+ *
+ * "buflen" should be positive. Caller holds the dcache_lock.
  */
-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-                     struct dentry *root, struct vfsmount *rootmnt,
-                     char *buffer, int buflen, int fail_deleted)
+static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+                       struct dentry *root, struct vfsmount *rootmnt,
+                       char *buffer, int buflen)
 {
-       int namelen, is_slash;
-
-       if (buflen < 2)
-               return ERR_PTR(-ENAMETOOLONG);
-       buffer += --buflen;
-       *buffer = '\0';
+       char * end = buffer+buflen;
+       char * retval;
+       int namelen;
 
-       spin_lock(&dcache_lock);
+       *--end = '\0';
+       buflen--;
        if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
-               if (fail_deleted) {
-                       buffer = ERR_PTR(-ENOENT);
-                       goto out;
-               }
-               if (buflen < 10)
-                       goto Elong;
                buflen -= 10;
-               buffer -= 10;
-               memcpy(buffer, " (deleted)", 10);
+               end -= 10;
+               if (buflen < 0)
+                       goto Elong;
+               memcpy(end, " (deleted)", 10);
        }
-       while (dentry != root || vfsmnt != rootmnt) {
+
+       if (buflen < 1)
+               goto Elong;
+       /* Get '/' right */
+       retval = end-1;
+       *retval = '/';
+
+       for (;;) {
                struct dentry * parent;
 
+               if (dentry == root && vfsmnt == rootmnt)
+                       break;
                if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+                       /* Global root? */
                        spin_lock(&vfsmount_lock);
                        if (vfsmnt->mnt_parent == vfsmnt) {
                                spin_unlock(&vfsmount_lock);
@@ -1787,60 +1791,33 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
                parent = dentry->d_parent;
                prefetch(parent);
                namelen = dentry->d_name.len;
-               if (buflen <= namelen)
-                       goto Elong;
                buflen -= namelen + 1;
-               buffer -= namelen;
-               memcpy(buffer, dentry->d_name.name, namelen);
-               *--buffer = '/';
+               if (buflen < 0)
+                       goto Elong;
+               end -= namelen;
+               memcpy(end, dentry->d_name.name, namelen);
+               *--end = '/';
+               retval = end;
                dentry = parent;
        }
-       /* Get '/' right */
-       if (*buffer != '/')
-               *--buffer = '/';
 
-out:
-       spin_unlock(&dcache_lock);
-       return buffer;
+       return retval;
 
 global_root:
-       /*
-        * We went past the (vfsmount, dentry) we were looking for and have
-        * either hit a root dentry, a lazily unmounted dentry, an
-        * unconnected dentry, or the file is on a pseudo filesystem.
-        */
        namelen = dentry->d_name.len;
-       is_slash = (namelen == 1 && *dentry->d_name.name == '/');
-       if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
-               /*
-                * Make sure we won't return a pathname starting with '/'.
-                *
-                * Historically, we also glue together the root dentry and
-                * remaining name for pseudo filesystems like pipefs, which
-                * have the MS_NOUSER flag set. This results in pathnames
-                * like "pipe:[439336]".
-                */
-               if (*buffer == '/') {
-                       buffer++;
-                       buflen++;
-               }
-               if (is_slash)
-                       goto out;
-       }
-       if (buflen < namelen)
+       buflen -= namelen;
+       if (buflen < 0)
                goto Elong;
-       buffer -= namelen;
-       memcpy(buffer, dentry->d_name.name, namelen);
-       goto out;
-
+       retval -= namelen-1;    /* hit the slash */
+       memcpy(retval, dentry->d_name.name, namelen);
+       return retval;
 Elong:
-       buffer = ERR_PTR(-ENAMETOOLONG);
-       goto out;
+       return ERR_PTR(-ENAMETOOLONG);
 }
 
 /* write full pathname into buffer and return start of pathname */
-char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
-            int buflen)
+char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+                               char *buf, int buflen)
 {
        char *res;
        struct vfsmount *rootmnt;
@@ -1850,7 +1827,9 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
        rootmnt = mntget(current->fs->rootmnt);
        root = dget(current->fs->root);
        read_unlock(&current->fs->lock);
-       res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
+       spin_lock(&dcache_lock);
+       res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
+       spin_unlock(&dcache_lock);
        dput(root);
        mntput(rootmnt);
        return res;
@@ -1876,10 +1855,10 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
  */
 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
 {
-       int error, len;
+       int error;
        struct vfsmount *pwdmnt, *rootmnt;
        struct dentry *pwd, *root;
-       char *page = (char *) __get_free_page(GFP_USER), *cwd;
+       char *page = (char *) __get_free_page(GFP_USER);
 
        if (!page)
                return -ENOMEM;
@@ -1891,18 +1870,29 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
        root = dget(current->fs->root);
        read_unlock(&current->fs->lock);
 
-       cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
-       error = PTR_ERR(cwd);
-       if (IS_ERR(cwd))
-               goto out;
+       error = -ENOENT;
+       /* Has the current directory has been unlinked? */
+       spin_lock(&dcache_lock);
+       if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
+               unsigned long len;
+               char * cwd;
 
-       error = -ERANGE;
-       len = PAGE_SIZE + page - cwd;
-       if (len <= size) {
-               error = len;
-               if (copy_to_user(buf, cwd, len))
-                       error = -EFAULT;
-       }
+               cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
+               spin_unlock(&dcache_lock);
+
+               error = PTR_ERR(cwd);
+               if (IS_ERR(cwd))
+                       goto out;
+
+               error = -ERANGE;
+               len = PAGE_SIZE + page - cwd;
+               if (len <= size) {
+                       error = len;
+                       if (copy_to_user(buf, cwd, len))
+                               error = -EFAULT;
+               }
+       } else
+               spin_unlock(&dcache_lock);
 
 out:
        dput(pwd);
index c1a2409..8578869 100644 (file)
@@ -69,7 +69,10 @@ static __inline__ void atomic_add(int i, atomic_t * v)
                "1:     ll      %0, %1          # atomic_add            \n"
                "       addu    %0, %2                                  \n"
                "       sc      %0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter));
@@ -111,7 +114,10 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
                "1:     ll      %0, %1          # atomic_sub            \n"
                "       subu    %0, %2                                  \n"
                "       sc      %0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter));
@@ -155,8 +161,11 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
                "1:     ll      %1, %2          # atomic_add_return     \n"
                "       addu    %0, %1, %3                              \n"
                "       sc      %0, %2                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "       addu    %0, %1, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -204,8 +213,11 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
                "1:     ll      %1, %2          # atomic_sub_return     \n"
                "       subu    %0, %1, %3                              \n"
                "       sc      %0, %2                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "       subu    %0, %1, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -267,10 +279,13 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
                "       bltz    %0, 1f                                  \n"
                "       sc      %0, %2                                  \n"
                "       .set    noreorder                               \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "        subu   %0, %1, %3                              \n"
                "       .set    reorder                                 \n"
                "1:                                                     \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -429,7 +444,10 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
                "1:     lld     %0, %1          # atomic64_add          \n"
                "       addu    %0, %2                                  \n"
                "       scd     %0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter));
@@ -471,7 +489,10 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
                "1:     lld     %0, %1          # atomic64_sub          \n"
                "       subu    %0, %2                                  \n"
                "       scd     %0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter));
@@ -515,8 +536,11 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
                "1:     lld     %1, %2          # atomic64_add_return   \n"
                "       addu    %0, %1, %3                              \n"
                "       scd     %0, %2                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "       addu    %0, %1, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -564,8 +588,11 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
                "1:     lld     %1, %2          # atomic64_sub_return   \n"
                "       subu    %0, %1, %3                              \n"
                "       scd     %0, %2                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "       subu    %0, %1, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -627,10 +654,13 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
                "       bltz    %0, 1f                                  \n"
                "       scd     %0, %2                                  \n"
                "       .set    noreorder                               \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
                "        dsubu  %0, %1, %3                              \n"
                "       .set    reorder                                 \n"
                "1:                                                     \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
index 06445de..06c0822 100644 (file)
@@ -68,7 +68,10 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                "1:     " __LL "%0, %1                  # set_bit       \n"
                "       or      %0, %2                                  \n"
                "       " __SC  "%0, %1                                 \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -116,7 +119,10 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                "1:     " __LL "%0, %1                  # clear_bit     \n"
                "       and     %0, %2                                  \n"
                "       " __SC "%0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
@@ -166,7 +172,10 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                "1:     " __LL "%0, %1          # change_bit    \n"
                "       xor     %0, %2                          \n"
                "       " __SC  "%0, %1                         \n"
-               "       beqz    %0, 1b                          \n"
+               "       beqz    %0, 2f                          \n"
+               "       .subsection 2                           \n"
+               "2:     b       1b                              \n"
+               "       .previous                               \n"
                "       .set    mips0                           \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -222,8 +231,12 @@ static inline int test_and_set_bit(unsigned long nr,
                "1:     " __LL "%0, %1          # test_and_set_bit      \n"
                "       or      %2, %0, %3                              \n"
                "       " __SC  "%2, %1                                 \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -290,8 +303,12 @@ static inline int test_and_clear_bit(unsigned long nr,
                "       or      %2, %0, %3                              \n"
                "       xor     %2, %3                                  \n"
                "       " __SC  "%2, %1                                 \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -356,8 +373,12 @@ static inline int test_and_change_bit(unsigned long nr,
                "1:     " __LL  "%0, %1         # test_and_change_bit   \n"
                "       xor     %2, %0, %3                              \n"
                "       " __SC  "\t%2, %1                               \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
diff --git a/include/asm-mips/compat-signal.h b/include/asm-mips/compat-signal.h
new file mode 100644 (file)
index 0000000..6720770
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __ASM_COMPAT_SIGNAL_H
+#define __ASM_COMPAT_SIGNAL_H
+
+#include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/compiler.h>
+
+static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
+       const sigset_t *s)
+{
+       int err;
+
+       BUG_ON(sizeof(*d) != sizeof(*s));
+       BUG_ON(_NSIG_WORDS != 2);
+
+       err  = __put_user(s->sig[0],       &d->sig[0]);
+       err |= __put_user(s->sig[0] >> 32, &d->sig[1]);
+       err |= __put_user(s->sig[1],       &d->sig[2]);
+       err |= __put_user(s->sig[1] >> 32, &d->sig[3]);
+
+       return err;
+}
+
+static inline int __copy_conv_sigset_from_user(sigset_t *d,
+       const compat_sigset_t __user *s)
+{
+       int err;
+       union sigset_u {
+               sigset_t        s;
+               compat_sigset_t c;
+       } *u = (union sigset_u *) d;
+
+       BUG_ON(sizeof(*d) != sizeof(*s));
+       BUG_ON(_NSIG_WORDS != 2);
+
+       if (unlikely(!access_ok(VERIFY_READ, d, sizeof(*d))))
+               return -EFAULT;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       err  = __get_user(u->c.sig[1], &s->sig[0]);
+       err |= __get_user(u->c.sig[0], &s->sig[1]);
+       err |= __get_user(u->c.sig[3], &s->sig[2]);
+       err |= __get_user(u->c.sig[2], &s->sig[3]);
+#endif
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+       err  = __get_user(u->c.sig[0], &s->sig[0]);
+       err |= __get_user(u->c.sig[1], &s->sig[1]);
+       err |= __get_user(u->c.sig[2], &s->sig[2]);
+       err |= __get_user(u->c.sig[3], &s->sig[3]);
+#endif
+
+       return err;
+}
+
+#endif /* __ASM_COMPAT_SIGNAL_H */
index 236d1a4..230b3f1 100644 (file)
@@ -68,6 +68,7 @@ extern int dma_is_consistent(struct device *dev, dma_addr_t dma_addr);
 extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction);
 
+#if 0
 #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 
 extern int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
@@ -75,5 +76,6 @@ extern int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
 extern void dma_release_declared_memory(struct device *dev);
 extern void * dma_mark_declared_memory_occupied(struct device *dev,
        dma_addr_t device_addr, size_t size);
+#endif
 
 #endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-mips/mach-generic/dma-coherence.h b/include/asm-mips/mach-generic/dma-coherence.h
new file mode 100644 (file)
index 0000000..df71822
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H
+#define __ASM_MACH_GENERIC_DMA_COHERENCE_H
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+       return virt_to_phys(addr);
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+       return page_to_phys(page);
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+       return dma_addr;
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+       return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+       return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
index 410ab5f..b8e6deb 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef CONFIG_DMA_COHERENT
 /*
  * Total overkill for most systems but need as a safe default.
+ * Set this one if any device in the system might do non-coherent DMA.
  */
 #define ARCH_KMALLOC_MINALIGN  128
 #endif
diff --git a/include/asm-mips/mach-ip27/dma-coherence.h b/include/asm-mips/mach-ip27/dma-coherence.h
new file mode 100644 (file)
index 0000000..659816e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_IP27_DMA_COHERENCE_H
+#define __ASM_MACH_IP27_DMA_COHERENCE_H
+
+#include <asm/pci/bridge.h>
+
+#define pdev_to_baddr(pdev, addr) \
+       (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
+#define dev_to_baddr(dev, addr) \
+       pdev_to_baddr(to_pci_dev(dev), (addr))
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+       dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr));
+
+       return pa;
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+       dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page));
+
+       return pa;
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+       return dma_addr & (0xffUL << 56);
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+       return 1;               /* IP27 non-cohernet mode is unsupported */
+}
+
+#endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/include/asm-mips/mach-ip32/dma-coherence.h
new file mode 100644 (file)
index 0000000..950be17
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_IP35_DMA_COHERENCE_H
+#define __ASM_MACH_IP35_DMA_COHERENCE_H
+
+#include <asm/ip32/crime.h>
+
+struct device;
+
+/*
+ * Few notes.
+ * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
+ * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for
+ *    native-endian)
+ * 3. All other devices see memory as one big chunk at 0x40000000
+ * 4. Non-PCI devices will pass NULL as struct device*
+ *
+ * Thus we translate differently, depending on device.
+ */
+
+#define RAM_OFFSET_MASK 0x3fffffffUL
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+       dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK;
+
+       if (dev == NULL)
+               pa += CRIME_HI_MEM_BASE;
+
+       return pa;
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+       dma_addr_t pa;
+
+       pa = page_to_phys(page) & RAM_OFFSET_MASK;
+
+       if (dev == NULL)
+               pa += CRIME_HI_MEM_BASE;
+
+       return pa;
+}
+
+/* This is almost certainly wrong but it's what dma-ip32.c used to use  */
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+       unsigned long addr = dma_addr & RAM_OFFSET_MASK;
+
+       if (dma_addr >= 256*1024*1024)
+               addr += CRIME_HI_MEM_BASE;
+
+       return addr;
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+       return 0;               /* IP32 is non-cohernet */
+}
+
+#endif /* __ASM_MACH_IP35_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-jazz/dma-coherence.h b/include/asm-mips/mach-jazz/dma-coherence.h
new file mode 100644 (file)
index 0000000..d66979a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_JAZZ_DMA_COHERENCE_H
+#define __ASM_MACH_JAZZ_DMA_COHERENCE_H
+
+#include <asm/jazzdma.h>
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+       return vdma_alloc(virt_to_phys(addr), size);
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+       return vdma_alloc(page_to_phys(page), PAGE_SIZE);
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+       return vdma_log2phys(dma_addr);
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+       vdma_free(dma_addr);
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+       return 0;
+}
+
+#endif /* __ASM_MACH_JAZZ_DMA_COHERENCE_H */
index fc3217f..f1755d2 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999, 2000, 06 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 06 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_SPINLOCK_H
@@ -49,11 +49,18 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_spin_lock       \n"
                "1:     ll      %1, %2                                  \n"
-               "       bnez    %1, 1b                                  \n"
+               "       bnez    %1, 2f                                  \n"
                "        li     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
+               "       beqz    %1, 2f                                  \n"
                "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bnez    %1, 2b                                  \n"
+               "        li     %1, 1                                   \n"
+               "       b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (lock->lock), "=&r" (tmp)
                : "m" (lock->lock)
@@ -99,8 +106,12 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
                "1:     ll      %0, %3                                  \n"
                "       ori     %2, %0, 1                               \n"
                "       sc      %2, %1                                  \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        andi   %2, %0, 1                               \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder"
                : "=&r" (temp), "=m" (lock->lock), "=&r" (res)
                : "m" (lock->lock)
@@ -154,11 +165,18 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_read_lock       \n"
                "1:     ll      %1, %2                                  \n"
-               "       bltz    %1, 1b                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqz    %1, 1b                                  \n"
                "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bltz    %1, 2b                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -192,8 +210,12 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
                "1:     ll      %1, %2                                  \n"
                "       sub     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
+               "       beqz    %1, 2f                                  \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
                "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -222,11 +244,18 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_write_lock      \n"
                "1:     ll      %1, %2                                  \n"
-               "       bnez    %1, 1b                                  \n"
+               "       bnez    %1, 2f                                  \n"
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
+               "       beqz    %1, 2f                                  \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bnez    %1, 2b                                  \n"
+               "        lui    %1, 0x8000                              \n"
+               "       b       1b                                      \n"
                "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -322,12 +351,15 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
                "       bnez    %1, 2f                                  \n"
                "       lui     %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
-               "        nop                                            \n"
+               "       beqz    %1, 3f                                  \n"
+               "        li     %2, 1                                   \n"
+               "2:                                                     \n"
                __WEAK_ORDERING_MB
-               "       li      %2, 1                                   \n"
+               "       .subsection 2                                   \n"
+               "3:     b       1b                                      \n"
+               "        li     %2, 0                                   \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
-               "2:                                                     \n"
                : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
                : "m" (rw->lock)
                : "memory");
index 5e1289c..597a374 100644 (file)
@@ -110,7 +110,10 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
                "       move    %2, %z4                                 \n"
                "       .set    mips3                                   \n"
                "       sc      %2, %1                                  \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
                : "R" (*m), "Jr" (val)
@@ -155,7 +158,10 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
                "1:     lld     %0, %3                  # xchg_u64      \n"
                "       move    %2, %z4                                 \n"
                "       scd     %2, %1                                  \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
                : "R" (*m), "Jr" (val)
@@ -232,8 +238,11 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
                "       move    $1, %z4                                 \n"
                "       .set    mips3                                   \n"
                "       sc      $1, %1                                  \n"
-               "       beqz    $1, 1b                                  \n"
+               "       beqz    $1, 3f                                  \n"
                "2:                                                     \n"
+               "       .subsection 2                                   \n"
+               "3:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (retval), "=R" (*m)
                : "R" (*m), "Jr" (old), "Jr" (new)
@@ -283,8 +292,11 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
                "       bne     %0, %z3, 2f                             \n"
                "       move    $1, %z4                                 \n"
                "       scd     $1, %1                                  \n"
-               "       beqz    $1, 1b                                  \n"
+               "       beqz    $1, 3f                                  \n"
                "2:                                                     \n"
+               "       .subsection 2                                   \n"
+               "3:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (retval), "=R" (*m)
                : "R" (*m), "Jr" (old), "Jr" (new)
index 825fcbd..3eff8d8 100644 (file)
@@ -265,10 +265,14 @@ do {                                                                      \
  */
 #define __get_user_asm_ll32(val, addr)                                 \
 {                                                                      \
+       union {                                                         \
+               unsigned long long      l;                              \
+               __typeof__(*(addr))     t;                              \
+       } __gu_tmp;                                                     \
+                                                                       \
        __asm__ __volatile__(                                           \
        "1:     lw      %1, (%3)                                \n"     \
        "2:     lw      %D1, 4(%3)                              \n"     \
-       "       move    %0, $0                                  \n"     \
        "3:     .section        .fixup,\"ax\"                   \n"     \
        "4:     li      %0, %4                                  \n"     \
        "       move    %1, $0                                  \n"     \
@@ -279,8 +283,10 @@ do {                                                                       \
        "       " __UA_ADDR "   1b, 4b                          \n"     \
        "       " __UA_ADDR "   2b, 4b                          \n"     \
        "       .previous                                       \n"     \
-       : "=r" (__gu_err), "=&r" (val)                                  \
+       : "=r" (__gu_err), "=&r" (__gu_tmp.l)                           \
        : "0" (0), "r" (addr), "i" (-EFAULT));                          \
+                                                                       \
+       (val) = __gu_tmp.t;                                             \
 }
 
 /*