]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 May 2008 17:50:34 +0000 (10:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 May 2008 17:50:34 +0000 (10:50 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ehca: Wait for async events to finish before destroying QP
  IB/ipath: Fix SDMA error recovery in absence of link status change
  IB/ipath: Need to always request and handle PIO avail interrupts
  IB/ipath: Fix count of packets received by kernel
  IB/ipath: Return the correct opcode for RDMA WRITE with immediate
  IB/ipath: Fix bug that can leave sends disabled after freeze recovery
  IB/ipath: Only increment SSN if WQE is put on send queue
  IB/ipath: Only warn about prototype chip during init
  RDMA/cxgb3: Fix severe limit on userspace memory registration size
  RDMA/cxgb3: Don't add PBL memory to gen_pool in chunks

132 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
Documentation/s390/CommonIO
MAINTAINERS
arch/cris/kernel/sys_cris.c
arch/m32r/kernel/sys_m32r.c
arch/s390/Kconfig
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/ptrace.c
arch/s390/kvm/Kconfig
arch/s390/kvm/intercept.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/Makefile
arch/s390/mm/init.c
arch/s390/mm/page-states.c [new file with mode: 0644]
arch/sparc/kernel/process.c
arch/sparc/kernel/sys_sparc.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/mm/init.c
arch/um/Makefile
arch/um/drivers/line.c
arch/um/include/line.h
arch/x86/mm/pgtable_32.c
block/blk-core.c
block/blk-ioc.c
block/blk-merge.c
block/blk-sysfs.c
block/blk-tag.c
block/cfq-iosched.c
drivers/accessibility/Kconfig
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/pata_acpi.c
drivers/ata/pata_sch.c [new file with mode: 0644]
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/base/sys.c
drivers/block/aoe/aoecmd.c
drivers/char/sx.c
drivers/char/vt.c
drivers/md/raid10.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/saa7134/saa7134-video.c
drivers/net/irda/nsc-ircc.c
drivers/net/irda/smsc-ircc2.c
drivers/net/niu.c
drivers/net/usb/asix.c
drivers/net/wan/lapbether.c
drivers/net/wireless/iwlwifi/Kconfig
drivers/rtc/rtc-ds1511.c
drivers/s390/char/tty3270.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
drivers/s390/cio/cio_debug.h
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c
drivers/s390/cio/device_pgid.c
drivers/s390/s390mach.c
drivers/sbus/char/bpp.c
drivers/scsi/dpt_i2o.c
drivers/scsi/dpti.h
drivers/serial/serial_core.c
drivers/usb/host/Kconfig
drivers/usb/serial/iuu_phoenix.c
drivers/video/bw2.c
drivers/video/cg3.c
drivers/video/cg6.c
drivers/video/ffb.c
drivers/video/leo.c
drivers/video/p9100.c
drivers/video/tcx.c
fs/affs/affs.h
fs/affs/file.c
fs/affs/inode.c
fs/affs/namei.c
fs/affs/super.c
fs/bio.c
fs/inode.c
fs/locks.c
fs/pipe.c
fs/splice.c
fs/udf/namei.c
fs/udf/partition.c
fs/udf/super.c
fs/udf/udfdecl.h
include/asm-mn10300/processor.h
include/asm-s390/kvm_host.h
include/asm-s390/page.h
include/asm-s390/ptrace.h
include/asm-s390/system.h
include/asm-x86/pgtable_32.h
include/asm-x86/pgtable_64.h
include/linux/exportfs.h
include/linux/fs.h
include/linux/genhd.h
include/linux/ioprio.h
include/linux/libata.h
include/net/ip.h
include/net/xfrm.h
kernel/cpuset.c
kernel/relay.c
mm/filemap.c
mm/memory.c
mm/slub.c
net/atm/br2684.c
net/bridge/br_if.c
net/core/skbuff.c
net/dccp/feat.c
net/decnet/dn_route.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv6/route.c
net/mac80211/main.c
net/mac80211/rc80211_pid_debugfs.c
net/sched/act_simple.c
net/sched/sch_htb.c
sound/oss/kahlua.c

index c2992bc54f2f49f0f7caee130acf19205df7511a..8b22d7d8b99166b6db2e037644e9c5d7ff03695e 100644 (file)
@@ -92,7 +92,6 @@ prototypes:
        void (*destroy_inode)(struct inode *);
        void (*dirty_inode) (struct inode *);
        int (*write_inode) (struct inode *, int);
-       void (*put_inode) (struct inode *);
        void (*drop_inode) (struct inode *);
        void (*delete_inode) (struct inode *);
        void (*put_super) (struct super_block *);
@@ -115,7 +114,6 @@ alloc_inode:                no      no      no
 destroy_inode:         no
 dirty_inode:           no                              (must not sleep)
 write_inode:           no
-put_inode:             no
 drop_inode:            no                              !!!inode_lock!!!
 delete_inode:          no
 put_super:             yes     yes     no
index 81e5be6e6e356e8ab3feb4e92b972fd0862db1a9..b7522c6cbae3758f77cb12e22b78825e43a3796d 100644 (file)
@@ -205,7 +205,6 @@ struct super_operations {
 
         void (*dirty_inode) (struct inode *);
         int (*write_inode) (struct inode *, int);
-        void (*put_inode) (struct inode *);
         void (*drop_inode) (struct inode *);
         void (*delete_inode) (struct inode *);
         void (*put_super) (struct super_block *);
@@ -246,9 +245,6 @@ or bottom half).
        inode to disc.  The second parameter indicates whether the write
        should be synchronous or not, not all filesystems check this flag.
 
-  put_inode: called when the VFS inode is removed from the inode
-       cache.
-
   drop_inode: called when the last access to the inode is dropped,
        with the inode_lock spinlock held.
 
index 8fbc0a852870f2a972b4d17adae71ba866bc5975..bf0baa19ec24e875716e09490a2afeaecb86b5e2 100644 (file)
@@ -8,17 +8,6 @@ Command line parameters
 
   Enable logging of debug information in case of ccw device timeouts.
 
-
-* cio_msg = yes | no
-  
-  Determines whether information on found devices and sensed device 
-  characteristics should be shown during startup or when new devices are
-  found, i. e. messages of the types "Detected device 0.0.4711 on subchannel
-  0.0.0042" and "SenseID: Device 0.0.4711 reports: ...".
-
-  Default is off.
-
-
 * cio_ignore = {all} |
               {<device> | <range of devices>} |
               {!<device> | !<range of devices>}
index abe27871ad6a54c56b48789aa4480a020e863fee..f5583dc7ea39f1ec8c94cda7a3503bc484df3fba 100644 (file)
@@ -2112,12 +2112,10 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 
 INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe)
-P:     Auke Kok
-M:     auke-jan.h.kok@intel.com
-P:     Jesse Brandeburg
-M:     jesse.brandeburg@intel.com
 P:     Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
+P:     Jesse Brandeburg
+M:     jesse.brandeburg@intel.com
 P:     Bruce Allan
 M:     bruce.w.allan@intel.com
 P:     John Ronciak
index 8b9984197edcc57878356a56848c237ea06aa109..d124066e1728880b29dc8778d103b5fed1309a1b 100644 (file)
@@ -40,8 +40,11 @@ asmlinkage int sys_pipe(unsigned long __user * fildes)
         error = do_pipe(fd);
         unlock_kernel();
         if (!error) {
-                if (copy_to_user(fildes, fd, 2*sizeof(int)))
+                if (copy_to_user(fildes, fd, 2*sizeof(int))) {
+                       sys_close(fd[0]);
+                       sys_close(fd[1]);
                         error = -EFAULT;
+               }
         }
         return error;
 }
index 6d7a80fdad488676b8e69c43b0db180e68baf823..319c79720b8a2ba3860ff35fad5a20b2552210cc 100644 (file)
@@ -90,8 +90,11 @@ sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2,
 
        error = do_pipe(fd);
        if (!error) {
-               if (copy_to_user((void __user *)r0, fd, 2*sizeof(int)))
+               if (copy_to_user((void __user *)r0, fd, 2*sizeof(int))) {
+                       sys_close(fd[0]);
+                       sys_close(fd[1]);
                        error = -EFAULT;
+               }
        }
        return error;
 }
index 29a7940f284f62fa1f9e27508bc7d55f9b50aca4..1d035082e78eb15fc73f8f3b7b939af19eaa23ba 100644 (file)
@@ -430,6 +430,13 @@ config CMM_IUCV
          Select this option to enable the special message interface to
          the cooperative memory management.
 
+config PAGE_STATES
+       bool "Unused page notification"
+       help
+         This enables the notification of unused pages to the
+         hypervisor. The ESSA instruction is used to do the states
+         changes between a page that has content and the unused state.
+
 config VIRT_TIMER
        bool "Virtual CPU timer support"
        help
index 743d54f0b8dbb01e93c17f51be274bece0005f48..d003a6e16afb807df2ecbbcc6066de49f0784c33 100644 (file)
@@ -121,7 +121,7 @@ sys32_ptrace_wrapper:
        lgfr    %r3,%r3                 # long
        llgtr   %r4,%r4                 # long
        llgfr   %r5,%r5                 # long
-       jg      sys_ptrace              # branch to system call
+       jg      compat_sys_ptrace       # branch to system call
 
        .globl  sys32_alarm_wrapper
 sys32_alarm_wrapper:
index bdbb3bcd78a5d7088ed4cfd39f7fb444e2f15814..708cf9cf9a355e175d5b1cf4fbdc2b96732e7084 100644 (file)
@@ -279,8 +279,6 @@ sysc_do_restart:
        st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
 
 sysc_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-       bno     BASED(sysc_restore)
        tm      __TI_flags+3(%r9),_TIF_WORK_SVC
        bnz     BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_restore:
@@ -312,6 +310,8 @@ sysc_work_loop:
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       bno     BASED(sysc_restore)
        tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
        bo      BASED(sysc_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
@@ -602,12 +602,6 @@ io_no_vtime:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r1                # branch to standard irq handler
 io_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-#ifdef CONFIG_PREEMPT
-       bno     BASED(io_preempt)       # no -> check for preemptive scheduling
-#else
-       bno     BASED(io_restore)       # no-> skip resched & signal
-#endif
        tm      __TI_flags+3(%r9),_TIF_WORK_INT
        bnz     BASED(io_work)          # there is work to do (signals etc.)
 io_restore:
@@ -629,10 +623,18 @@ io_restore_trace_psw:
        .long   0, io_restore_trace + 0x80000000
 #endif
 
-#ifdef CONFIG_PREEMPT
-io_preempt:
+#
+# switch to kernel stack, then check the TIF bits
+#
+io_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+#ifndef CONFIG_PREEMPT
+       bno     BASED(io_restore)       # no-> skip resched & signal
+#else
+       bnz     BASED(io_work_user)     # no -> check for preemptive scheduling
+       # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
-       bnz     BASED(io_restore)
+       bnz     BASED(io_restore)       # preemption disabled
        l       %r1,SP_R15(%r15)
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
@@ -646,10 +648,7 @@ io_resume_loop:
        br      %r1                     # call schedule
 #endif
 
-#
-# switch to kernel stack, then check the TIF bits
-#
-io_work:
+io_work_user:
        l       %r1,__LC_KERNEL_STACK
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
index 5a4a7bcd2bbad8e92e95eb529fb11559977c0dd9..fee10177dbfcf67a175c7d82f1839886ef509ff4 100644 (file)
@@ -271,8 +271,6 @@ sysc_noemu:
        stg     %r2,SP_R2(%r15) # store return value (change R2 on stack)
 
 sysc_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-       jno     sysc_restore
        tm      __TI_flags+7(%r9),_TIF_WORK_SVC
        jnz     sysc_work       # there is work to do (signals etc.)
 sysc_restore:
@@ -304,6 +302,8 @@ sysc_work_loop:
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       jno     sysc_restore
        tm      __TI_flags+7(%r9),_TIF_MCCK_PENDING
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
@@ -585,12 +585,6 @@ io_no_vtime:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_IRQ             # call standard irq handler
 io_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-#ifdef CONFIG_PREEMPT
-       jno     io_preempt              # no -> check for preemptive scheduling
-#else
-       jno     io_restore              # no-> skip resched & signal
-#endif
        tm      __TI_flags+7(%r9),_TIF_WORK_INT
        jnz     io_work                 # there is work to do (signals etc.)
 io_restore:
@@ -612,10 +606,41 @@ io_restore_trace_psw:
        .quad   0, io_restore_trace
 #endif
 
-#ifdef CONFIG_PREEMPT
-io_preempt:
+#
+# There is work todo, we need to check if we return to userspace, then
+# check, if we are in SIE, if yes leave it
+#
+io_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+#ifndef CONFIG_PREEMPT
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       jnz     io_work_user            # yes -> no need to check for SIE
+       la      %r1, BASED(sie_opcode)  # we return to kernel here
+       lg      %r2, SP_PSW+8(%r15)
+       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
+       jne     io_restore              # no-> return to kernel
+       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
+       aghi    %r1, 4
+       stg     %r1, SP_PSW+8(%r15)
+       j       io_restore              # return to kernel
+#else
+       jno     io_restore              # no-> skip resched & signal
+#endif
+#else
+       jnz     io_work_user            # yes -> do resched & signal
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       la      %r1, BASED(sie_opcode)
+       lg      %r2, SP_PSW+8(%r15)
+       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
+       jne     0f                      # no -> leave PSW alone
+       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
+       aghi    %r1, 4
+       stg     %r1, SP_PSW+8(%r15)
+0:
+#endif
+       # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
-       jnz     io_restore
+       jnz     io_restore              # preemption is disabled
        # switch to kernel stack
        lg      %r1,SP_R15(%r15)
        aghi    %r1,-SP_SIZE
@@ -629,10 +654,7 @@ io_resume_loop:
        jg      preempt_schedule_irq
 #endif
 
-#
-# switch to kernel stack, then check TIF bits
-#
-io_work:
+io_work_user:
        lg      %r1,__LC_KERNEL_STACK
        aghi    %r1,-SP_SIZE
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
@@ -653,6 +675,11 @@ io_work_loop:
        j       io_restore
 io_work_done:
 
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+sie_opcode:
+       .long 0xb2140000
+#endif
+
 #
 # _TIF_MCCK_PENDING is set, call handler
 #
index 7f4270163744b1ea5af37b6a68ca69e2cef89437..35827b9bd4d1827f102f79f3e999bbb69c52f5ab 100644 (file)
@@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
-static int
-do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        ptrace_area parea; 
        int copied, ret;
@@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
-static int
-do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+                       compat_ulong_t caddr, compat_ulong_t cdata)
 {
-       unsigned int tmp;  /* 4 bytes !! */
+       unsigned long addr = caddr;
+       unsigned long data = cdata;
        ptrace_area_emu31 parea; 
        int copied, ret;
 
        switch (request) {
-       case PTRACE_PEEKTEXT:
-       case PTRACE_PEEKDATA:
-               /* read word at location addr. */
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-               if (copied != sizeof(tmp))
-                       return -EIO;
-               return put_user(tmp, (unsigned int __force __user *) data);
-
        case PTRACE_PEEKUSR:
                /* read the word at location addr in the USER area. */
                return peek_user_emu31(child, addr, data);
 
-       case PTRACE_POKETEXT:
-       case PTRACE_POKEDATA:
-               /* write the word at location addr. */
-               tmp = data;
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
-               if (copied != sizeof(tmp))
-                       return -EIO;
-               return 0;
-
        case PTRACE_POKEUSR:
                /* write the word at location addr in the USER area */
                return poke_user_emu31(child, addr, data);
@@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
                        copied += sizeof(unsigned int);
                }
                return 0;
-       case PTRACE_GETEVENTMSG:
-               return put_user((__u32) child->ptrace_message,
-                               (unsigned int __force __user *) data);
-       case PTRACE_GETSIGINFO:
-               if (child->last_siginfo == NULL)
-                       return -EINVAL;
-               return copy_siginfo_to_user32((compat_siginfo_t
-                                              __force __user *) data,
-                                             child->last_siginfo);
-       case PTRACE_SETSIGINFO:
-               if (child->last_siginfo == NULL)
-                       return -EINVAL;
-               return copy_siginfo_from_user32(child->last_siginfo,
-                                               (compat_siginfo_t
-                                                __force __user *) data);
        }
-       return ptrace_request(child, request, addr, data);
+       return compat_ptrace_request(child, request, addr, data);
 }
 #endif
 
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
-{
-       switch (request) {
-       case PTRACE_SYSCALL:
-               /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT:
-               /* restart after signal. */
-               if (!valid_signal(data))
-                       return -EIO;
-               if (request == PTRACE_SYSCALL)
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               else
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               /* make sure the single step bit is not set. */
-               user_disable_single_step(child);
-               wake_up_process(child);
-               return 0;
-
-       case PTRACE_KILL:
-               /*
-                * make the child exit.  Best I can do is send it a sigkill. 
-                * perhaps it should be put in the status that it wants to 
-                * exit.
-                */
-               if (child->exit_state == EXIT_ZOMBIE) /* already dead */
-                       return 0;
-               child->exit_code = SIGKILL;
-               /* make sure the single step bit is not set. */
-               user_disable_single_step(child);
-               wake_up_process(child);
-               return 0;
-
-       case PTRACE_SINGLESTEP:
-               /* set the trap flag. */
-               if (!valid_signal(data))
-                       return -EIO;
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               user_enable_single_step(child);
-               /* give it a chance to run. */
-               wake_up_process(child);
-               return 0;
-
-       /* Do requests that differ for 31/64 bit */
-       default:
-#ifdef CONFIG_COMPAT
-               if (test_thread_flag(TIF_31BIT))
-                       return do_ptrace_emu31(child, request, addr, data);
-#endif
-               return do_ptrace_normal(child, request, addr, data);
-       }
-       /* Not reached.  */
-       return -EIO;
-}
-
 asmlinkage void
 syscall_trace(struct pt_regs *regs, int entryexit)
 {
index 1761b74d639be88e3fbc870cda7a4942c7b50ac9..e051cad1f1e09d9f880b91f0d23b7738e10a5a57 100644 (file)
@@ -22,7 +22,6 @@ config KVM
        select PREEMPT_NOTIFIERS
        select ANON_INODES
        select S390_SWITCH_AMODE
-       select PREEMPT
        ---help---
          Support hosting paravirtualized guest machines using the SIE
          virtualization capability on the mainframe. This should work
index 349581a2610344f23c1af6873dc57d6c23761b47..47a0b642174c1ef807ca5d16774f9d10c6584197 100644 (file)
@@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = {
 static int handle_noop(struct kvm_vcpu *vcpu)
 {
        switch (vcpu->arch.sie_block->icptcode) {
+       case 0x0:
+               vcpu->stat.exit_null++;
+               break;
        case 0x10:
                vcpu->stat.exit_external_request++;
                break;
index 98d1e73e01f11f31cdac4d693f54c1bfddedc871..0ac36a649eba9a2823189d3bb31dcb68b0ec6055 100644 (file)
@@ -31,6 +31,7 @@
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "userspace_handled", VCPU_STAT(exit_userspace) },
+       { "exit_null", VCPU_STAT(exit_null) },
        { "exit_validity", VCPU_STAT(exit_validity) },
        { "exit_stop_request", VCPU_STAT(exit_stop_request) },
        { "exit_external_request", VCPU_STAT(exit_external_request) },
@@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
        restore_fp_regs(&vcpu->arch.guest_fpregs);
        restore_access_regs(vcpu->arch.guest_acrs);
-
-       if (signal_pending(current))
-               atomic_set_mask(CPUSTAT_STOP_INT,
-                       &vcpu->arch.sie_block->cpuflags);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
index fb988a48a754ff541d161ba341a108e10a2a15e1..2a745813454410cb35ff525e837efc9f29c0dd95 100644 (file)
@@ -5,3 +5,4 @@
 obj-y   := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_PAGE_STATES) += page-states.o
index fa31de6ae97aef1577b99d0f9afb04cf257334ce..29f3a63806b976ee8847dd3efd84292697ba53db 100644 (file)
@@ -126,6 +126,9 @@ void __init mem_init(void)
         /* clear the zero-page */
         memset(empty_zero_page, 0, PAGE_SIZE);
 
+       /* Setup guest page hinting */
+       cmma_init();
+
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem();
 
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
new file mode 100644 (file)
index 0000000..fc0ad73
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * arch/s390/mm/page-states.c
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Guest page hinting for unused pages.
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#define ESSA_SET_STABLE                1
+#define ESSA_SET_UNUSED                2
+
+static int cmma_flag;
+
+static int __init cmma(char *str)
+{
+       char *parm;
+       parm = strstrip(str);
+       if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) {
+               cmma_flag = 1;
+               return 1;
+       }
+       cmma_flag = 0;
+       if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0)
+               return 1;
+       return 0;
+}
+
+__setup("cmma=", cmma);
+
+void __init cmma_init(void)
+{
+       register unsigned long tmp asm("0") = 0;
+       register int rc asm("1") = -EOPNOTSUPP;
+
+       if (!cmma_flag)
+               return;
+       asm volatile(
+               "       .insn rrf,0xb9ab0000,%1,%1,0,0\n"
+               "0:     la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+&d" (rc), "+&d" (tmp));
+       if (rc)
+               cmma_flag = 0;
+}
+
+void arch_free_page(struct page *page, int order)
+{
+       int i, rc;
+
+       if (!cmma_flag)
+               return;
+       for (i = 0; i < (1 << order); i++)
+               asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
+                            : "=&d" (rc)
+                            : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
+                              "i" (ESSA_SET_UNUSED));
+}
+
+void arch_alloc_page(struct page *page, int order)
+{
+       int i, rc;
+
+       if (!cmma_flag)
+               return;
+       for (i = 0; i < (1 << order); i++)
+               asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
+                            : "=&d" (rc)
+                            : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
+                              "i" (ESSA_SET_STABLE));
+}
index e7f35198ae34943f5adfeeedd7223014dfe146ff..36431f377deed29c370077df39575a65a0c4ae3c 100644 (file)
@@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
                              unsigned long stack_size)
 {
        unsigned long parent_tid_ptr, child_tid_ptr;
+       unsigned long orig_i1 = regs->u_regs[UREG_I1];
+       long ret;
 
        parent_tid_ptr = regs->u_regs[UREG_I2];
        child_tid_ptr = regs->u_regs[UREG_I4];
 
-       return do_fork(clone_flags, stack_start,
-                      regs, stack_size,
-                      (int __user *) parent_tid_ptr,
-                      (int __user *) child_tid_ptr);
+       ret = do_fork(clone_flags, stack_start,
+                     regs, stack_size,
+                     (int __user *) parent_tid_ptr,
+                     (int __user *) child_tid_ptr);
+
+       /* If we get an error and potentially restart the system
+        * call, we're screwed because copy_thread() clobbered
+        * the parent's %o1.  So detect that case and restore it
+        * here.
+        */
+       if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
+               regs->u_regs[UREG_I1] = orig_i1;
+
+       return ret;
 }
 
 /* Copy a Sparc thread.  The fork() return value conventions
index f188b5dc9fd001bec3691b03401408b5af655ce4..e995491c443627d5e0e1b5f363990608b946685f 100644 (file)
@@ -223,8 +223,7 @@ int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
 {
        if (ARCH_SUN4C_SUN4 &&
            (len > 0x20000000 ||
-            ((flags & MAP_FIXED) &&
-             addr < 0xe0000000 && addr + len > 0x20000000)))
+            (addr < 0xe0000000 && addr + len > 0x20000000)))
                return -EINVAL;
 
        /* See asm-sparc/uaccess.h */
index 500ac6d483a0cec74f7c8ab51940167813267127..4129c0449856bbe61a34e670ec87996cd71bd19a 100644 (file)
@@ -503,6 +503,8 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
                              unsigned long stack_size)
 {
        int __user *parent_tid_ptr, *child_tid_ptr;
+       unsigned long orig_i1 = regs->u_regs[UREG_I1];
+       long ret;
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
@@ -515,9 +517,19 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
                child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
        }
 
-       return do_fork(clone_flags, stack_start,
-                      regs, stack_size,
-                      parent_tid_ptr, child_tid_ptr);
+       ret = do_fork(clone_flags, stack_start,
+                     regs, stack_size,
+                     parent_tid_ptr, child_tid_ptr);
+
+       /* If we get an error and potentially restart the system
+        * call, we're screwed because copy_thread() clobbered
+        * the parent's %o1.  So detect that case and restore it
+        * here.
+        */
+       if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
+               regs->u_regs[UREG_I1] = orig_i1;
+
+       return ret;
 }
 
 /* Copy a Sparc thread.  The fork() return value conventions
index 3aba47624df45aa0e773c169fe6498b5bb5e377e..0d6403a630acd1f4c2e22201755d67de04a83cc1 100644 (file)
@@ -865,21 +865,14 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
        void *info = call_data->info;
 
        clear_softint(1 << irq);
-
-       irq_enter();
-
-       if (!call_data->wait) {
-               /* let initiator proceed after getting data */
-               atomic_inc(&call_data->finished);
-       }
-
-       func(info);
-
-       irq_exit();
-
        if (call_data->wait) {
                /* let initiator proceed only after completion */
+               func(info);
                atomic_inc(&call_data->finished);
+       } else {
+               /* let initiator proceed after getting data */
+               atomic_inc(&call_data->finished);
+               func(info);
        }
 }
 
@@ -1041,9 +1034,7 @@ void smp_receive_signal(int cpu)
 
 void smp_receive_signal_client(int irq, struct pt_regs *regs)
 {
-       irq_enter();
        clear_softint(1 << irq);
-       irq_exit();
 }
 
 void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
@@ -1051,8 +1042,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
        struct mm_struct *mm;
        unsigned long flags;
 
-       irq_enter();
-
        clear_softint(1 << irq);
 
        /* See if we need to allocate a new TLB context because
@@ -1072,8 +1061,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
        load_secondary_context(mm);
        __flush_tlb_mm(CTX_HWBITS(mm->context),
                       SECONDARY_CONTEXT);
-
-       irq_exit();
 }
 
 void smp_new_mmu_context_version(void)
@@ -1239,8 +1226,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
 {
        clear_softint(1 << irq);
 
-       irq_enter();
-
        preempt_disable();
 
        __asm__ __volatile__("flushw");
@@ -1253,8 +1238,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
        prom_world(0);
 
        preempt_enable();
-
-       irq_exit();
 }
 
 /* /proc/profile writes can call this, don't __init it please. */
index 8d4761f15fa932cdede6dc4dc4336fdaa2b1cc88..0dbc941f130e6f8163422b0e42306bc68d226162 100644 (file)
@@ -549,13 +549,13 @@ int sparc64_mmap_check(unsigned long addr, unsigned long len,
                if (len >= STACK_TOP32)
                        return -EINVAL;
 
-               if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len)
+               if (addr > STACK_TOP32 - len)
                        return -EINVAL;
        } else {
                if (len >= VA_EXCLUDE_START)
                        return -EINVAL;
 
-               if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
+               if (invalid_64bit_range(addr, len))
                        return -EINVAL;
        }
 
index 161ce4710fe76143326905011db732358de7c891..1aa4288125f25906eb5fddea19ddeff3c6bac493 100644 (file)
@@ -236,13 +236,6 @@ asmlinkage long sys32_getegid16(void)
 
 /* 32-bit timeval and related flotsam.  */
 
-static long get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
-       return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-               (__get_user(o->tv_sec, &i->tv_sec) |
-                __get_user(o->tv_usec, &i->tv_usec)));
-}
-
 static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
 {
        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
@@ -757,30 +750,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
        return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-asmlinkage long sys32_utimes(char __user *filename,
-                            struct compat_timeval __user *tvs)
-{
-       struct timespec tv[2];
-
-       if (tvs) {
-               struct timeval ktvs[2];
-               if (get_tv32(&ktvs[0], tvs) ||
-                   get_tv32(&ktvs[1], 1+tvs))
-                       return -EFAULT;
-
-               if (ktvs[0].tv_usec < 0 || ktvs[0].tv_usec >= 1000000 ||
-                   ktvs[1].tv_usec < 0 || ktvs[1].tv_usec >= 1000000)
-                       return -EINVAL;
-
-               tv[0].tv_sec = ktvs[0].tv_sec;
-               tv[0].tv_nsec = 1000 * ktvs[0].tv_usec;
-               tv[1].tv_sec = ktvs[1].tv_sec;
-               tv[1].tv_nsec = 1000 * ktvs[1].tv_usec;
-       }
-
-       return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
-}
-
 /* These are here just in case some old sparc32 binary calls it. */
 asmlinkage long sys32_pause(void)
 {
index a4fef2ba1ae162848d801034f7cf18008b10b8de..8b5282d433c44b6c1d04ebaf525cda6470b9a9f2 100644 (file)
@@ -45,7 +45,7 @@ sys_call_table32:
 /*120*/        .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
        .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
 /*130*/        .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
-       .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64
+       .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
 /*140*/        .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
        .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/        .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
index 4cad0b32b0afcd5256dce395a1ce6e682c50715c..ec3e2c72302a78a66c5da100c892f4328117a7e3 100644 (file)
@@ -771,6 +771,9 @@ static void __init find_ramdisk(unsigned long phys_base)
                initrd_end = ramdisk_image + sparc_ramdisk_size;
 
                lmb_reserve(initrd_start, initrd_end);
+
+               initrd_start += PAGE_OFFSET;
+               initrd_end += PAGE_OFFSET;
        }
 #endif
 }
@@ -2362,16 +2365,3 @@ void __flush_tlb_all(void)
        __asm__ __volatile__("wrpr      %0, 0, %%pstate"
                             : : "r" (pstate));
 }
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-
-void online_page(struct page *page)
-{
-       ClearPageReserved(page);
-       init_page_count(page);
-       __free_page(page);
-       totalram_pages++;
-       num_physpages++;
-}
-
-#endif /* CONFIG_MEMORY_HOTPLUG */
index 01b97c19a8ba99da4a07db8194397b1611b265e6..dbeab15e7bb7c160db7dda887a4c9d14982f742c 100644 (file)
@@ -77,10 +77,7 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
                         -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES))
 KBUILD_CFLAGS += $(KERNEL_DEFINES)
-# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
-# a lot more stack due to the lack of sharing of stacklots:
-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
-                       echo $(call cc-option,-fno-unit-at-a-time); fi ;)
+KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
 
 PHONY += linux
 
index 10b86e1cc659ee8ca02bee67c2e931067eef8de2..5047490fc299aa69ae999b348760277767684569 100644 (file)
@@ -191,9 +191,9 @@ void line_flush_chars(struct tty_struct *tty)
        line_flush_buffer(tty);
 }
 
-void line_put_char(struct tty_struct *tty, unsigned char ch)
+int line_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       line_write(tty, &ch, sizeof(ch));
+       return line_write(tty, &ch, sizeof(ch));
 }
 
 int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
index 1223f2c844b4085c798e79400419bcb718dc979c..979b73e6352d1995e4a928d3b2d26350875a9034 100644 (file)
@@ -71,7 +71,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines,
                      char *init, char **error_out);
 extern int line_write(struct tty_struct *tty, const unsigned char *buf,
                      int len);
-extern void line_put_char(struct tty_struct *tty, unsigned char ch);
+extern int line_put_char(struct tty_struct *tty, unsigned char ch);
 extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
 extern int line_chars_in_buffer(struct tty_struct *tty);
 extern void line_flush_buffer(struct tty_struct *tty);
index 9ee007be914299ab8dae9d3f52df22ae606816f1..369cf065b6a48f78f9870ddaf9f27e59b6980c0c 100644 (file)
@@ -172,10 +172,3 @@ void reserve_top_address(unsigned long reserve)
        __FIXADDR_TOP = -reserve - PAGE_SIZE;
        __VMALLOC_RESERVE += reserve;
 }
-
-int pmd_bad(pmd_t pmd)
-{
-       WARN_ON_ONCE(pmd_bad_v1(pmd) != pmd_bad_v2(pmd));
-
-       return pmd_bad_v1(pmd);
-}
index b754a4a2f9bd26e2e3aaed11fb6fa3a9c3d67d0b..2987fe47b5eecaa565bce30a7c3d661813453351 100644 (file)
@@ -54,15 +54,16 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
 
 static void drive_stat_acct(struct request *rq, int new_io)
 {
+       struct hd_struct *part;
        int rw = rq_data_dir(rq);
 
        if (!blk_fs_request(rq) || !rq->rq_disk)
                return;
 
-       if (!new_io) {
-               __all_stat_inc(rq->rq_disk, merges[rw], rq->sector);
-       } else {
-               struct hd_struct *part = get_part(rq->rq_disk, rq->sector);
+       part = get_part(rq->rq_disk, rq->sector);
+       if (!new_io)
+               __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector);
+       else {
                disk_round_stats(rq->rq_disk);
                rq->rq_disk->in_flight++;
                if (part) {
@@ -253,9 +254,11 @@ EXPORT_SYMBOL(__generic_unplug_device);
  **/
 void generic_unplug_device(struct request_queue *q)
 {
-       spin_lock_irq(q->queue_lock);
-       __generic_unplug_device(q);
-       spin_unlock_irq(q->queue_lock);
+       if (blk_queue_plugged(q)) {
+               spin_lock_irq(q->queue_lock);
+               __generic_unplug_device(q);
+               spin_unlock_irq(q->queue_lock);
+       }
 }
 EXPORT_SYMBOL(generic_unplug_device);
 
@@ -1536,10 +1539,11 @@ static int __end_that_request_first(struct request *req, int error,
        }
 
        if (blk_fs_request(req) && req->rq_disk) {
+               struct hd_struct *part = get_part(req->rq_disk, req->sector);
                const int rw = rq_data_dir(req);
 
-               all_stat_add(req->rq_disk, sectors[rw],
-                            nr_bytes >> 9, req->sector);
+               all_stat_add(req->rq_disk, part, sectors[rw],
+                               nr_bytes >> 9, req->sector);
        }
 
        total_bytes = bio_nbytes = 0;
@@ -1725,8 +1729,8 @@ static void end_that_request_last(struct request *req, int error)
                const int rw = rq_data_dir(req);
                struct hd_struct *part = get_part(disk, req->sector);
 
-               __all_stat_inc(disk, ios[rw], req->sector);
-               __all_stat_add(disk, ticks[rw], duration, req->sector);
+               __all_stat_inc(disk, part, ios[rw], req->sector);
+               __all_stat_add(disk, part, ticks[rw], duration, req->sector);
                disk_round_stats(disk);
                disk->in_flight--;
                if (part) {
index e34df7c9fc367048de2c9e669a70291922467ba9..012f065ac8e248d4e42485a7ef9a728692bb43a1 100644 (file)
@@ -41,8 +41,8 @@ int put_io_context(struct io_context *ioc)
                rcu_read_lock();
                if (ioc->aic && ioc->aic->dtor)
                        ioc->aic->dtor(ioc->aic);
-               rcu_read_unlock();
                cfq_dtor(ioc);
+               rcu_read_unlock();
 
                kmem_cache_free(iocontext_cachep, ioc);
                return 1;
index 73b23562af20086f3a8623df6e9f32561ae330b5..651136aae76e45ba821205a830a919a3d6d105c5 100644 (file)
@@ -149,9 +149,9 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
 static int blk_hw_contig_segment(struct request_queue *q, struct bio *bio,
                                 struct bio *nxt)
 {
-       if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+       if (!bio_flagged(bio, BIO_SEG_VALID))
                blk_recount_segments(q, bio);
-       if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
+       if (!bio_flagged(nxt, BIO_SEG_VALID))
                blk_recount_segments(q, nxt);
        if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
            BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
@@ -312,9 +312,9 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
                        q->last_merge = NULL;
                return 0;
        }
-       if (unlikely(!bio_flagged(req->biotail, BIO_SEG_VALID)))
+       if (!bio_flagged(req->biotail, BIO_SEG_VALID))
                blk_recount_segments(q, req->biotail);
-       if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+       if (!bio_flagged(bio, BIO_SEG_VALID))
                blk_recount_segments(q, bio);
        len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size;
        if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio))
@@ -352,9 +352,9 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req,
                return 0;
        }
        len = bio->bi_hw_back_size + req->bio->bi_hw_front_size;
-       if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+       if (!bio_flagged(bio, BIO_SEG_VALID))
                blk_recount_segments(q, bio);
-       if (unlikely(!bio_flagged(req->bio, BIO_SEG_VALID)))
+       if (!bio_flagged(req->bio, BIO_SEG_VALID))
                blk_recount_segments(q, req->bio);
        if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) &&
            !BIOVEC_VIRT_OVERSIZE(len)) {
index e85c4013e8a29a5924c4657447a2b6611eb17702..304ec73ab8215f270cbea1a50e870fd8b5b7bf54 100644 (file)
@@ -146,11 +146,13 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
        unsigned long nm;
        ssize_t ret = queue_var_store(&nm, page, count);
 
+       spin_lock_irq(q->queue_lock);
        if (nm)
-              set_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
+               queue_flag_set(QUEUE_FLAG_NOMERGES, q);
        else
-              clear_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
+               queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
 
+       spin_unlock_irq(q->queue_lock);
        return ret;
 }
 
index de64e04299771f08eebb391616d63b72c2fca64a..32667beb03eebf4d04b283f0a0cac999d66ad3e7 100644 (file)
@@ -70,7 +70,7 @@ void __blk_queue_free_tags(struct request_queue *q)
        __blk_free_tags(bqt);
 
        q->queue_tags = NULL;
-       queue_flag_clear(QUEUE_FLAG_QUEUED, q);
+       queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q);
 }
 
 /**
@@ -98,7 +98,7 @@ EXPORT_SYMBOL(blk_free_tags);
  **/
 void blk_queue_free_tags(struct request_queue *q)
 {
-       queue_flag_clear(QUEUE_FLAG_QUEUED, q);
+       queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q);
 }
 EXPORT_SYMBOL(blk_queue_free_tags);
 
@@ -171,6 +171,9 @@ EXPORT_SYMBOL(blk_init_tags);
  * @q:  the request queue for the device
  * @depth:  the maximum queue depth supported
  * @tags: the tag to use
+ *
+ * Queue lock must be held here if the function is called to resize an
+ * existing map.
  **/
 int blk_queue_init_tags(struct request_queue *q, int depth,
                        struct blk_queue_tag *tags)
@@ -197,7 +200,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
         * assign it, all done
         */
        q->queue_tags = tags;
-       queue_flag_set(QUEUE_FLAG_QUEUED, q);
+       queue_flag_set_unlocked(QUEUE_FLAG_QUEUED, q);
        INIT_LIST_HEAD(&q->tag_busy_list);
        return 0;
 fail:
index f4e1006c253d3ade81cc9b39ce80da6612b277a6..b399c62936e01a503715273ffef29ac2fafef8a4 100644 (file)
@@ -1142,6 +1142,17 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
        kmem_cache_free(cfq_pool, cfqq);
 }
 
+static void
+__call_for_each_cic(struct io_context *ioc,
+                   void (*func)(struct io_context *, struct cfq_io_context *))
+{
+       struct cfq_io_context *cic;
+       struct hlist_node *n;
+
+       hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
+               func(ioc, cic);
+}
+
 /*
  * Call func for each cic attached to this ioc.
  */
@@ -1149,12 +1160,8 @@ static void
 call_for_each_cic(struct io_context *ioc,
                  void (*func)(struct io_context *, struct cfq_io_context *))
 {
-       struct cfq_io_context *cic;
-       struct hlist_node *n;
-
        rcu_read_lock();
-       hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
-               func(ioc, cic);
+       __call_for_each_cic(ioc, func);
        rcu_read_unlock();
 }
 
@@ -1198,7 +1205,7 @@ static void cfq_free_io_context(struct io_context *ioc)
         * should be ok to iterate over the known list, we will see all cic's
         * since no new ones are added.
         */
-       call_for_each_cic(ioc, cic_free_func);
+       __call_for_each_cic(ioc, cic_free_func);
 }
 
 static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@ -1296,10 +1303,10 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
                printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
        case IOPRIO_CLASS_NONE:
                /*
-                * no prio set, place us in the middle of the BE classes
+                * no prio set, inherit CPU scheduling settings
                 */
                cfqq->ioprio = task_nice_ioprio(tsk);
-               cfqq->ioprio_class = IOPRIO_CLASS_BE;
+               cfqq->ioprio_class = task_nice_ioclass(tsk);
                break;
        case IOPRIO_CLASS_RT:
                cfqq->ioprio = task_ioprio(ioc);
index 1264c4b980942447afbade6fe1f0c947e311aea1..ef3b65bfdd0ac57d49a323174fab431b167c69c0 100644 (file)
@@ -1,7 +1,17 @@
 menuconfig ACCESSIBILITY
        bool "Accessibility support"
        ---help---
-         Enable a submenu where accessibility items may be enabled.
+         Accessibility handles all special kinds of hardware devices or
+         software adapters which help people with disabilities (e.g.
+         blindness) to use computers.
+
+         That includes braille devices, speech synthesis, keyboard
+         remapping, etc.
+
+         Say Y here to get to see options for accessibility.
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
 
          If unsure, say N.
 
index 1c11df9a5f32a92e3ff7fda7700450deccf228b4..9bf2986a2788d6bd11e26bdd459bdf9ed376fcb5 100644 (file)
@@ -205,8 +205,8 @@ config SATA_VITESSE
          If unsure, say N.
 
 config SATA_INIC162X
-       tristate "Initio 162x SATA support (HIGHLY EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Initio 162x SATA support"
+       depends on PCI
        help
          This option enables support for Initio 162x Serial ATA.
 
@@ -697,6 +697,15 @@ config PATA_SCC
 
          If unsure, say N.
 
+config PATA_SCH
+       tristate "Intel SCH PATA support"
+       depends on PCI
+       help
+         This option enables support for Intel SCH PATA on the Intel
+         SCH (US15W, US15L, UL11L) series host controllers.
+
+         If unsure, say N.
+
 config PATA_BF54X
        tristate "Blackfin 54x ATAPI support"
        depends on BF542 || BF548 || BF549
index b693d829383a3b7ff9e33bd0d181523f23297379..674965fa326dafa621311ed92dfcc91d80380296 100644 (file)
@@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_SIS)                += pata_sis.o
 obj-$(CONFIG_PATA_TRIFLEX)     += pata_triflex.o
 obj-$(CONFIG_PATA_IXP4XX_CF)   += pata_ixp4xx_cf.o
 obj-$(CONFIG_PATA_SCC)         += pata_scc.o
+obj-$(CONFIG_PATA_SCH)         += pata_sch.o
 obj-$(CONFIG_PATA_BF54X)       += pata_bf54x.o
 obj-$(CONFIG_PATA_PLATFORM)    += pata_platform.o
 obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
index 8cace9aa9c0398bafe101115ba511bb5dd29f0fb..97f83fb2ee2eef25af748297cb474c859ba6545e 100644 (file)
@@ -1267,9 +1267,7 @@ static int ahci_check_ready(struct ata_link *link)
        void __iomem *port_mmio = ahci_port_base(link->ap);
        u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
 
-       if (!(status & ATA_BUSY))
-               return 1;
-       return 0;
+       return ata_check_ready(status);
 }
 
 static int ahci_softreset(struct ata_link *link, unsigned int *class,
index 47aeccd52fa951b900bacd63d4af7e71cf370039..75a406f5e6945525d4799bc44de7ccf6e1552feb 100644 (file)
@@ -152,6 +152,12 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
        if (dev->vendor == PCI_VENDOR_ID_AL)
                ata_pci_bmdma_clear_simplex(dev);
 
+       if (dev->vendor == PCI_VENDOR_ID_ATI) {
+               int rc = pcim_enable_device(dev);
+               if (rc < 0)
+                       return rc;
+               pcim_pin_device(dev);
+       }
        return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
 }
 
index ea2c7649d399b38c70c987703246de96e9e2b00a..a9027b8fbdd53fbb7ea3e2b6257a84924375b9f3 100644 (file)
@@ -1348,6 +1348,8 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        struct piix_host_priv *hpriv = host->private_data;
+       struct ata_device *dev0 = &host->ports[0]->link.device[0];
+       u32 scontrol;
        int i;
 
        /* check for availability */
@@ -1366,6 +1368,29 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
                return;
 
        hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
+
+       /* SCR access via SIDPR doesn't work on some configurations.
+        * Give it a test drive by inhibiting power save modes which
+        * we'll do anyway.
+        */
+       scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+
+       /* if IPM is already 3, SCR access is probably working.  Don't
+        * un-inhibit power save modes as BIOS might have inhibited
+        * them for a reason.
+        */
+       if ((scontrol & 0xf00) != 0x300) {
+               scontrol |= 0x300;
+               piix_sidpr_write(dev0, SCR_CONTROL, scontrol);
+               scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+
+               if ((scontrol & 0xf00) != 0x300) {
+                       dev_printk(KERN_INFO, host->dev, "SCR access via "
+                                  "SIDPR is available but doesn't work\n");
+                       return;
+               }
+       }
+
        host->ports[0]->ops = &piix_sidpr_sata_ops;
        host->ports[1]->ops = &piix_sidpr_sata_ops;
 }
index 3bc488538204abe225b388346d3b2a65a1c5ed5d..927b692d723cb190f73e30d09891bf62336770ea 100644 (file)
@@ -6292,6 +6292,7 @@ EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
 EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+EXPORT_SYMBOL_GPL(ata_eh_analyze_ncq_error);
 EXPORT_SYMBOL_GPL(ata_do_eh);
 EXPORT_SYMBOL_GPL(ata_std_error_handler);
 
index 61dcd0026c64c301c8ce43a0ec89e5eebaf755f8..62e033146bedae50c7de7126f0f3a8b2aec67b17 100644 (file)
@@ -1357,7 +1357,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)
  *     LOCKING:
  *     Kernel thread context (may sleep).
  */
-static void ata_eh_analyze_ncq_error(struct ata_link *link)
+void ata_eh_analyze_ncq_error(struct ata_link *link)
 {
        struct ata_port *ap = link->ap;
        struct ata_eh_context *ehc = &link->eh_context;
index 2ec65a8fda79ecc46986ed0da6de7d886c71ccf5..3c2d2289f85ee3233c259a4508fdb134e969053d 100644 (file)
@@ -314,11 +314,7 @@ static int ata_sff_check_ready(struct ata_link *link)
 {
        u8 status = link->ap->ops->sff_check_status(link->ap);
 
-       if (!(status & ATA_BUSY))
-               return 1;
-       if (status == 0xff)
-               return -ENODEV;
-       return 0;
+       return ata_check_ready(status);
 }
 
 /**
index c5f91e629945040130f53a28bd6bc7b920f87b36..fbe605711554a24dd1ae23be66d02128c8193b18 100644 (file)
@@ -259,6 +259,12 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
                .port_ops       = &pacpi_ops,
        };
        const struct ata_port_info *ppi[] = { &info, NULL };
+       if (pdev->vendor == PCI_VENDOR_ID_ATI) {
+               int rc = pcim_enable_device(pdev);
+               if (rc < 0)
+                       return rc;
+               pcim_pin_device(pdev);
+       }
        return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL);
 }
 
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
new file mode 100644 (file)
index 0000000..c8cc027
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  pata_sch.c - Intel SCH PATA controllers
+ *
+ *  Copyright (c) 2008 Alek Du <alek.du@intel.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ *  Supports:
+ *    Intel SCH (AF82US15W, AF82US15L, AF82UL11L) chipsets -- see spec at:
+ *    http://download.intel.com/design/chipsets/embedded/datashts/319537.pdf
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <linux/dmi.h>
+
+#define DRV_NAME       "pata_sch"
+#define DRV_VERSION    "0.2"
+
+/* see SCH datasheet page 351 */
+enum {
+       D0TIM   = 0x80,         /* Device 0 Timing Register */
+       D1TIM   = 0x84,         /* Device 1 Timing Register */
+       PM      = 0x07,         /* PIO Mode Bit Mask */
+       MDM     = (0x03 << 8),  /* Multi-word DMA Mode Bit Mask */
+       UDM     = (0x07 << 16), /* Ultra DMA Mode Bit Mask */
+       PPE     = (1 << 30),    /* Prefetch/Post Enable */
+       USD     = (1 << 31),    /* Use Synchronous DMA */
+};
+
+static int sch_init_one(struct pci_dev *pdev,
+                        const struct pci_device_id *ent);
+static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev);
+static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+
+static const struct pci_device_id sch_pci_tbl[] = {
+       /* Intel SCH PATA Controller */
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_IDE), 0 },
+       { }     /* terminate list */
+};
+
+static struct pci_driver sch_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = sch_pci_tbl,
+       .probe                  = sch_init_one,
+       .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
+};
+
+static struct scsi_host_template sch_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations sch_pata_ops = {
+       .inherits               = &ata_bmdma_port_ops,
+       .cable_detect           = ata_cable_unknown,
+       .set_piomode            = sch_set_piomode,
+       .set_dmamode            = sch_set_dmamode,
+};
+
+static struct ata_port_info sch_port_info = {
+       .flags          = 0,
+       .pio_mask       = ATA_PIO4,   /* pio0-4 */
+       .mwdma_mask     = ATA_MWDMA2, /* mwdma0-2 */
+       .udma_mask      = ATA_UDMA5,  /* udma0-5 */
+       .port_ops       = &sch_pata_ops,
+};
+
+MODULE_AUTHOR("Alek Du <alek.du@intel.com>");
+MODULE_DESCRIPTION("SCSI low-level driver for Intel SCH PATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sch_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+/**
+ *     sch_set_piomode - Initialize host controller PATA PIO timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: ATA device
+ *
+ *     Set PIO mode for device, in host controller PCI config space.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
+       struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned int port       = adev->devno ? D1TIM : D0TIM;
+       unsigned int data;
+
+       pci_read_config_dword(dev, port, &data);
+       /* see SCH datasheet page 351 */
+       /* set PIO mode */
+       data &= ~(PM | PPE);
+       data |= pio;
+       /* enable PPE for block device */
+       if (adev->class == ATA_DEV_ATA)
+               data |= PPE;
+       pci_write_config_dword(dev, port, data);
+}
+
+/**
+ *     sch_set_dmamode - Initialize host controller PATA DMA timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: ATA device
+ *
+ *     Set MW/UDMA mode for device, in host controller PCI config space.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int dma_mode   = adev->dma_mode;
+       struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned int port       = adev->devno ? D1TIM : D0TIM;
+       unsigned int data;
+
+       pci_read_config_dword(dev, port, &data);
+       /* see SCH datasheet page 351 */
+       if (dma_mode >= XFER_UDMA_0) {
+               /* enable Synchronous DMA mode */
+               data |= USD;
+               data &= ~UDM;
+               data |= (dma_mode - XFER_UDMA_0) << 16;
+       } else { /* must be MWDMA mode, since we masked SWDMA already */
+               data &= ~(USD | MDM);
+               data |= (dma_mode - XFER_MW_DMA_0) << 8;
+       }
+       pci_write_config_dword(dev, port, data);
+}
+
+/**
+ *     sch_init_one - Register SCH ATA PCI device with kernel services
+ *     @pdev: PCI device to register
+ *     @ent: Entry in sch_pci_tbl matching with @pdev
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, or -ERRNO value.
+ */
+
+static int __devinit sch_init_one(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+{
+       static int printed_version;
+       const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
+       struct ata_host *host;
+       int rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "version " DRV_VERSION "\n");
+
+       /* enable device and prepare host */
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
+       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       if (rc)
+               return rc;
+       pci_set_master(pdev);
+       return ata_pci_sff_activate_host(host, ata_sff_interrupt, &sch_sht);
+}
+
+static int __init sch_init(void)
+{
+       return pci_register_driver(&sch_pci_driver);
+}
+
+static void __exit sch_exit(void)
+{
+       pci_unregister_driver(&sch_pci_driver);
+}
+
+module_init(sch_init);
+module_exit(sch_exit);
index d27bb9a2568f77678e82dfbc032df8045daa4b94..3ead02fe379e26ca1dac0130a323e06888ba7f35 100644 (file)
  * right.  Documentation is available at initio's website but it only
  * documents registers (not programming model).
  *
- * - ATA disks work.
- * - Hotplug works.
- * - ATAPI read works but burning doesn't.  This thing is really
- *   peculiar about ATAPI and I couldn't figure out how ATAPI PIO and
- *   ATAPI DMA WRITE should be programmed.  If you've got a clue, be
- *   my guest.
- * - Both STR and STD work.
+ * This driver has interesting history.  The first version was written
+ * from the documentation and a 2.4 IDE driver posted on a Taiwan
+ * company, which didn't use any IDMA features and couldn't handle
+ * LBA48.  The resulting driver couldn't handle LBA48 devices either
+ * making it pretty useless.
+ *
+ * After a while, initio picked the driver up, renamed it to
+ * sata_initio162x, updated it to use IDMA for ATA DMA commands and
+ * posted it on their website.  It only used ATA_PROT_DMA for IDMA and
+ * attaching both devices and issuing IDMA and !IDMA commands
+ * simultaneously broke it due to PIRQ masking interaction but it did
+ * show how to use the IDMA (ADMA + some initio specific twists)
+ * engine.
+ *
+ * Then, I picked up their changes again and here's the usable driver
+ * which uses IDMA for everything.  Everything works now including
+ * LBA48, CD/DVD burning, suspend/resume and hotplug.  There are some
+ * issues tho.  Result Tf is not resported properly, NCQ isn't
+ * supported yet and CD/DVD writing works with DMA assisted PIO
+ * protocol (which, for native SATA devices, shouldn't cause any
+ * noticeable difference).
+ *
+ * Anyways, so, here's finally a working driver for inic162x.  Enjoy!
+ *
+ * initio: If you guys wanna improve the driver regarding result TF
+ * access and other stuff, please feel free to contact me.  I'll be
+ * happy to assist.
  */
 
 #include <linux/kernel.h>
 #include <scsi/scsi_device.h>
 
 #define DRV_NAME       "sata_inic162x"
-#define DRV_VERSION    "0.3"
+#define DRV_VERSION    "0.4"
 
 enum {
-       MMIO_BAR                = 5,
+       MMIO_BAR_PCI            = 5,
+       MMIO_BAR_CARDBUS        = 1,
 
        NR_PORTS                = 2,
 
+       IDMA_CPB_TBL_SIZE       = 4 * 32,
+
+       INIC_DMA_BOUNDARY       = 0xffffff,
+
+       HOST_ACTRL              = 0x08,
        HOST_CTL                = 0x7c,
        HOST_STAT               = 0x7e,
        HOST_IRQ_STAT           = 0xbc,
@@ -43,22 +69,37 @@ enum {
        PORT_SIZE               = 0x40,
 
        /* registers for ATA TF operation */
-       PORT_TF                 = 0x00,
-       PORT_ALT_STAT           = 0x08,
+       PORT_TF_DATA            = 0x00,
+       PORT_TF_FEATURE         = 0x01,
+       PORT_TF_NSECT           = 0x02,
+       PORT_TF_LBAL            = 0x03,
+       PORT_TF_LBAM            = 0x04,
+       PORT_TF_LBAH            = 0x05,
+       PORT_TF_DEVICE          = 0x06,
+       PORT_TF_COMMAND         = 0x07,
+       PORT_TF_ALT_STAT        = 0x08,
        PORT_IRQ_STAT           = 0x09,
        PORT_IRQ_MASK           = 0x0a,
        PORT_PRD_CTL            = 0x0b,
        PORT_PRD_ADDR           = 0x0c,
        PORT_PRD_XFERLEN        = 0x10,
+       PORT_CPB_CPBLAR         = 0x18,
+       PORT_CPB_PTQFIFO        = 0x1c,
 
        /* IDMA register */
        PORT_IDMA_CTL           = 0x14,
+       PORT_IDMA_STAT          = 0x16,
+
+       PORT_RPQ_FIFO           = 0x1e,
+       PORT_RPQ_CNT            = 0x1f,
 
        PORT_SCR                = 0x20,
 
        /* HOST_CTL bits */
        HCTL_IRQOFF             = (1 << 8),  /* global IRQ off */
-       HCTL_PWRDWN             = (1 << 13), /* power down PHYs */
+       HCTL_FTHD0              = (1 << 10), /* fifo threshold 0 */
+       HCTL_FTHD1              = (1 << 11), /* fifo threshold 1*/
+       HCTL_PWRDWN             = (1 << 12), /* power down PHYs */
        HCTL_SOFTRST            = (1 << 13), /* global reset (no phy reset) */
        HCTL_RPGSEL             = (1 << 15), /* register page select */
 
@@ -81,9 +122,7 @@ enum {
        PIRQ_PENDING            = (1 << 7),  /* port IRQ pending (STAT only) */
 
        PIRQ_ERR                = PIRQ_OFFLINE | PIRQ_ONLINE | PIRQ_FATAL,
-
-       PIRQ_MASK_DMA_READ      = PIRQ_REPLY | PIRQ_ATA,
-       PIRQ_MASK_OTHER         = PIRQ_REPLY | PIRQ_COMPLETE,
+       PIRQ_MASK_DEFAULT       = PIRQ_REPLY | PIRQ_ATA,
        PIRQ_MASK_FREEZE        = 0xff,
 
        /* PORT_PRD_CTL bits */
@@ -96,20 +135,104 @@ enum {
        IDMA_CTL_RST_IDMA       = (1 << 5),  /* reset IDMA machinary */
        IDMA_CTL_GO             = (1 << 7),  /* IDMA mode go */
        IDMA_CTL_ATA_NIEN       = (1 << 8),  /* ATA IRQ disable */
+
+       /* PORT_IDMA_STAT bits */
+       IDMA_STAT_PERR          = (1 << 0),  /* PCI ERROR MODE */
+       IDMA_STAT_CPBERR        = (1 << 1),  /* ADMA CPB error */
+       IDMA_STAT_LGCY          = (1 << 3),  /* ADMA legacy */
+       IDMA_STAT_UIRQ          = (1 << 4),  /* ADMA unsolicited irq */
+       IDMA_STAT_STPD          = (1 << 5),  /* ADMA stopped */
+       IDMA_STAT_PSD           = (1 << 6),  /* ADMA pause */
+       IDMA_STAT_DONE          = (1 << 7),  /* ADMA done */
+
+       IDMA_STAT_ERR           = IDMA_STAT_PERR | IDMA_STAT_CPBERR,
+
+       /* CPB Control Flags*/
+       CPB_CTL_VALID           = (1 << 0),  /* CPB valid */
+       CPB_CTL_QUEUED          = (1 << 1),  /* queued command */
+       CPB_CTL_DATA            = (1 << 2),  /* data, rsvd in datasheet */
+       CPB_CTL_IEN             = (1 << 3),  /* PCI interrupt enable */
+       CPB_CTL_DEVDIR          = (1 << 4),  /* device direction control */
+
+       /* CPB Response Flags */
+       CPB_RESP_DONE           = (1 << 0),  /* ATA command complete */
+       CPB_RESP_REL            = (1 << 1),  /* ATA release */
+       CPB_RESP_IGNORED        = (1 << 2),  /* CPB ignored */
+       CPB_RESP_ATA_ERR        = (1 << 3),  /* ATA command error */
+       CPB_RESP_SPURIOUS       = (1 << 4),  /* ATA spurious interrupt error */
+       CPB_RESP_UNDERFLOW      = (1 << 5),  /* APRD deficiency length error */
+       CPB_RESP_OVERFLOW       = (1 << 6),  /* APRD exccess length error */
+       CPB_RESP_CPB_ERR        = (1 << 7),  /* CPB error flag */
+
+       /* PRD Control Flags */
+       PRD_DRAIN               = (1 << 1),  /* ignore data excess */
+       PRD_CDB                 = (1 << 2),  /* atapi packet command pointer */
+       PRD_DIRECT_INTR         = (1 << 3),  /* direct interrupt */
+       PRD_DMA                 = (1 << 4),  /* data transfer method */
+       PRD_WRITE               = (1 << 5),  /* data dir, rsvd in datasheet */
+       PRD_IOM                 = (1 << 6),  /* io/memory transfer */
+       PRD_END                 = (1 << 7),  /* APRD chain end */
 };
 
+/* Comman Parameter Block */
+struct inic_cpb {
+       u8              resp_flags;     /* Response Flags */
+       u8              error;          /* ATA Error */
+       u8              status;         /* ATA Status */
+       u8              ctl_flags;      /* Control Flags */
+       __le32          len;            /* Total Transfer Length */
+       __le32          prd;            /* First PRD pointer */
+       u8              rsvd[4];
+       /* 16 bytes */
+       u8              feature;        /* ATA Feature */
+       u8              hob_feature;    /* ATA Ex. Feature */
+       u8              device;         /* ATA Device/Head */
+       u8              mirctl;         /* Mirror Control */
+       u8              nsect;          /* ATA Sector Count */
+       u8              hob_nsect;      /* ATA Ex. Sector Count */
+       u8              lbal;           /* ATA Sector Number */
+       u8              hob_lbal;       /* ATA Ex. Sector Number */
+       u8              lbam;           /* ATA Cylinder Low */
+       u8              hob_lbam;       /* ATA Ex. Cylinder Low */
+       u8              lbah;           /* ATA Cylinder High */
+       u8              hob_lbah;       /* ATA Ex. Cylinder High */
+       u8              command;        /* ATA Command */
+       u8              ctl;            /* ATA Control */
+       u8              slave_error;    /* Slave ATA Error */
+       u8              slave_status;   /* Slave ATA Status */
+       /* 32 bytes */
+} __packed;
+
+/* Physical Region Descriptor */
+struct inic_prd {
+       __le32          mad;            /* Physical Memory Address */
+       __le16          len;            /* Transfer Length */
+       u8              rsvd;
+       u8              flags;          /* Control Flags */
+} __packed;
+
+struct inic_pkt {
+       struct inic_cpb cpb;
+       struct inic_prd prd[LIBATA_MAX_PRD + 1];        /* + 1 for cdb */
+       u8              cdb[ATAPI_CDB_LEN];
+} __packed;
+
 struct inic_host_priv {
-       u16     cached_hctl;
+       void __iomem    *mmio_base;
+       u16             cached_hctl;
 };
 
 struct inic_port_priv {
-       u8      dfl_prdctl;
-       u8      cached_prdctl;
-       u8      cached_pirq_mask;
+       struct inic_pkt *pkt;
+       dma_addr_t      pkt_dma;
+       u32             *cpb_tbl;
+       dma_addr_t      cpb_tbl_dma;
 };
 
 static struct scsi_host_template inic_sht = {
-       ATA_BMDMA_SHT(DRV_NAME),
+       ATA_BASE_SHT(DRV_NAME),
+       .sg_tablesize   = LIBATA_MAX_PRD,       /* maybe it can be larger? */
+       .dma_boundary   = INIC_DMA_BOUNDARY,
 };
 
 static const int scr_map[] = {
@@ -120,54 +243,34 @@ static const int scr_map[] = {
 
 static void __iomem *inic_port_base(struct ata_port *ap)
 {
-       return ap->host->iomap[MMIO_BAR] + ap->port_no * PORT_SIZE;
-}
-
-static void __inic_set_pirq_mask(struct ata_port *ap, u8 mask)
-{
-       void __iomem *port_base = inic_port_base(ap);
-       struct inic_port_priv *pp = ap->private_data;
+       struct inic_host_priv *hpriv = ap->host->private_data;
 
-       writeb(mask, port_base + PORT_IRQ_MASK);
-       pp->cached_pirq_mask = mask;
-}
-
-static void inic_set_pirq_mask(struct ata_port *ap, u8 mask)
-{
-       struct inic_port_priv *pp = ap->private_data;
-
-       if (pp->cached_pirq_mask != mask)
-               __inic_set_pirq_mask(ap, mask);
+       return hpriv->mmio_base + ap->port_no * PORT_SIZE;
 }
 
 static void inic_reset_port(void __iomem *port_base)
 {
        void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
-       u16 ctl;
 
-       ctl = readw(idma_ctl);
-       ctl &= ~(IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN | IDMA_CTL_GO);
+       /* stop IDMA engine */
+       readw(idma_ctl); /* flush */
+       msleep(1);
 
        /* mask IRQ and assert reset */
-       writew(ctl | IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN, idma_ctl);
+       writew(IDMA_CTL_RST_IDMA, idma_ctl);
        readw(idma_ctl); /* flush */
-
-       /* give it some time */
        msleep(1);
 
        /* release reset */
-       writew(ctl | IDMA_CTL_ATA_NIEN, idma_ctl);
+       writew(0, idma_ctl);
 
        /* clear irq */
        writeb(0xff, port_base + PORT_IRQ_STAT);
-
-       /* reenable ATA IRQ, turn off IDMA mode */
-       writew(ctl, idma_ctl);
 }
 
 static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
 {
-       void __iomem *scr_addr = ap->ioaddr.scr_addr;
+       void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
        void __iomem *addr;
 
        if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -184,120 +287,126 @@ static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
 
 static int inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-       void __iomem *scr_addr = ap->ioaddr.scr_addr;
-       void __iomem *addr;
+       void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
 
        if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
                return -EINVAL;
 
-       addr = scr_addr + scr_map[sc_reg] * 4;
        writel(val, scr_addr + scr_map[sc_reg] * 4);
        return 0;
 }
 
-/*
- * In TF mode, inic162x is very similar to SFF device.  TF registers
- * function the same.  DMA engine behaves similary using the same PRD
- * format as BMDMA but different command register, interrupt and event
- * notification methods are used.  The following inic_bmdma_*()
- * functions do the impedance matching.
- */
-static void inic_bmdma_setup(struct ata_queued_cmd *qc)
+static void inic_stop_idma(struct ata_port *ap)
 {
-       struct ata_port *ap = qc->ap;
-       struct inic_port_priv *pp = ap->private_data;
        void __iomem *port_base = inic_port_base(ap);
-       int rw = qc->tf.flags & ATA_TFLAG_WRITE;
-
-       /* make sure device sees PRD table writes */
-       wmb();
-
-       /* load transfer length */
-       writel(qc->nbytes, port_base + PORT_PRD_XFERLEN);
-
-       /* turn on DMA and specify data direction */
-       pp->cached_prdctl = pp->dfl_prdctl | PRD_CTL_DMAEN;
-       if (!rw)
-               pp->cached_prdctl |= PRD_CTL_WR;
-       writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
 
-       /* issue r/w command */
-       ap->ops->sff_exec_command(ap, &qc->tf);
+       readb(port_base + PORT_RPQ_FIFO);
+       readb(port_base + PORT_RPQ_CNT);
+       writew(0, port_base + PORT_IDMA_CTL);
 }
 
-static void inic_bmdma_start(struct ata_queued_cmd *qc)
+static void inic_host_err_intr(struct ata_port *ap, u8 irq_stat, u16 idma_stat)
 {
-       struct ata_port *ap = qc->ap;
+       struct ata_eh_info *ehi = &ap->link.eh_info;
        struct inic_port_priv *pp = ap->private_data;
-       void __iomem *port_base = inic_port_base(ap);
+       struct inic_cpb *cpb = &pp->pkt->cpb;
+       bool freeze = false;
 
-       /* start host DMA transaction */
-       pp->cached_prdctl |= PRD_CTL_START;
-       writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
-}
+       ata_ehi_clear_desc(ehi);
+       ata_ehi_push_desc(ehi, "irq_stat=0x%x idma_stat=0x%x",
+                         irq_stat, idma_stat);
 
-static void inic_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct inic_port_priv *pp = ap->private_data;
-       void __iomem *port_base = inic_port_base(ap);
+       inic_stop_idma(ap);
 
-       /* stop DMA engine */
-       writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL);
-}
+       if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
+               ata_ehi_push_desc(ehi, "hotplug");
+               ata_ehi_hotplugged(ehi);
+               freeze = true;
+       }
 
-static u8 inic_bmdma_status(struct ata_port *ap)
-{
-       /* event is already verified by the interrupt handler */
-       return ATA_DMA_INTR;
+       if (idma_stat & IDMA_STAT_PERR) {
+               ata_ehi_push_desc(ehi, "PCI error");
+               freeze = true;
+       }
+
+       if (idma_stat & IDMA_STAT_CPBERR) {
+               ata_ehi_push_desc(ehi, "CPB error");
+
+               if (cpb->resp_flags & CPB_RESP_IGNORED) {
+                       __ata_ehi_push_desc(ehi, " ignored");
+                       ehi->err_mask |= AC_ERR_INVALID;
+                       freeze = true;
+               }
+
+               if (cpb->resp_flags & CPB_RESP_ATA_ERR)
+                       ehi->err_mask |= AC_ERR_DEV;
+
+               if (cpb->resp_flags & CPB_RESP_SPURIOUS) {
+                       __ata_ehi_push_desc(ehi, " spurious-intr");
+                       ehi->err_mask |= AC_ERR_HSM;
+                       freeze = true;
+               }
+
+               if (cpb->resp_flags &
+                   (CPB_RESP_UNDERFLOW | CPB_RESP_OVERFLOW)) {
+                       __ata_ehi_push_desc(ehi, " data-over/underflow");
+                       ehi->err_mask |= AC_ERR_HSM;
+                       freeze = true;
+               }
+       }
+
+       if (freeze)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
 }
 
 static void inic_host_intr(struct ata_port *ap)
 {
        void __iomem *port_base = inic_port_base(ap);
-       struct ata_eh_info *ehi = &ap->link.eh_info;
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
        u8 irq_stat;
+       u16 idma_stat;
 
-       /* fetch and clear irq */
+       /* read and clear IRQ status */
        irq_stat = readb(port_base + PORT_IRQ_STAT);
        writeb(irq_stat, port_base + PORT_IRQ_STAT);
+       idma_stat = readw(port_base + PORT_IDMA_STAT);
 
-       if (likely(!(irq_stat & PIRQ_ERR))) {
-               struct ata_queued_cmd *qc =
-                       ata_qc_from_tag(ap, ap->link.active_tag);
+       if (unlikely((irq_stat & PIRQ_ERR) || (idma_stat & IDMA_STAT_ERR)))
+               inic_host_err_intr(ap, irq_stat, idma_stat);
 
-               if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
-                       ap->ops->sff_check_status(ap); /* clear ATA interrupt */
-                       return;
-               }
+       if (unlikely(!qc))
+               goto spurious;
 
-               if (likely(ata_sff_host_intr(ap, qc)))
-                       return;
+       if (likely(idma_stat & IDMA_STAT_DONE)) {
+               inic_stop_idma(ap);
 
-               ap->ops->sff_check_status(ap); /* clear ATA interrupt */
-               ata_port_printk(ap, KERN_WARNING, "unhandled "
-                               "interrupt, irq_stat=%x\n", irq_stat);
+               /* Depending on circumstances, device error
+                * isn't reported by IDMA, check it explicitly.
+                */
+               if (unlikely(readb(port_base + PORT_TF_COMMAND) &
+                            (ATA_DF | ATA_ERR)))
+                       qc->err_mask |= AC_ERR_DEV;
+
+               ata_qc_complete(qc);
                return;
        }
 
-       /* error */
-       ata_ehi_push_desc(ehi, "irq_stat=0x%x", irq_stat);
-
-       if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
-               ata_ehi_hotplugged(ehi);
-               ata_port_freeze(ap);
-       } else
-               ata_port_abort(ap);
+ spurious:
+       ata_port_printk(ap, KERN_WARNING, "unhandled interrupt: "
+                       "cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
+                       qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
 }
 
 static irqreturn_t inic_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
-       void __iomem *mmio_base = host->iomap[MMIO_BAR];
+       struct inic_host_priv *hpriv = host->private_data;
        u16 host_irq_stat;
        int i, handled = 0;;
 
-       host_irq_stat = readw(mmio_base + HOST_IRQ_STAT);
+       host_irq_stat = readw(hpriv->mmio_base + HOST_IRQ_STAT);
 
        if (unlikely(!(host_irq_stat & HIRQ_GLOBAL)))
                goto out;
@@ -327,60 +436,173 @@ static irqreturn_t inic_interrupt(int irq, void *dev_instance)
        return IRQ_RETVAL(handled);
 }
 
+static int inic_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       /* For some reason ATAPI_PROT_DMA doesn't work for some
+        * commands including writes and other misc ops.  Use PIO
+        * protocol instead, which BTW is driven by the DMA engine
+        * anyway, so it shouldn't make much difference for native
+        * SATA devices.
+        */
+       if (atapi_cmd_type(qc->cdb[0]) == READ)
+               return 0;
+       return 1;
+}
+
+static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc)
+{
+       struct scatterlist *sg;
+       unsigned int si;
+       u8 flags = 0;
+
+       if (qc->tf.flags & ATA_TFLAG_WRITE)
+               flags |= PRD_WRITE;
+
+       if (ata_is_dma(qc->tf.protocol))
+               flags |= PRD_DMA;
+
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
+               prd->mad = cpu_to_le32(sg_dma_address(sg));
+               prd->len = cpu_to_le16(sg_dma_len(sg));
+               prd->flags = flags;
+               prd++;
+       }
+
+       WARN_ON(!si);
+       prd[-1].flags |= PRD_END;
+}
+
+static void inic_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct inic_port_priv *pp = qc->ap->private_data;
+       struct inic_pkt *pkt = pp->pkt;
+       struct inic_cpb *cpb = &pkt->cpb;
+       struct inic_prd *prd = pkt->prd;
+       bool is_atapi = ata_is_atapi(qc->tf.protocol);
+       bool is_data = ata_is_data(qc->tf.protocol);
+       unsigned int cdb_len = 0;
+
+       VPRINTK("ENTER\n");
+
+       if (is_atapi)
+               cdb_len = qc->dev->cdb_len;
+
+       /* prepare packet, based on initio driver */
+       memset(pkt, 0, sizeof(struct inic_pkt));
+
+       cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN;
+       if (is_atapi || is_data)
+               cpb->ctl_flags |= CPB_CTL_DATA;
+
+       cpb->len = cpu_to_le32(qc->nbytes + cdb_len);
+       cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd));
+
+       cpb->device = qc->tf.device;
+       cpb->feature = qc->tf.feature;
+       cpb->nsect = qc->tf.nsect;
+       cpb->lbal = qc->tf.lbal;
+       cpb->lbam = qc->tf.lbam;
+       cpb->lbah = qc->tf.lbah;
+
+       if (qc->tf.flags & ATA_TFLAG_LBA48) {
+               cpb->hob_feature = qc->tf.hob_feature;
+               cpb->hob_nsect = qc->tf.hob_nsect;
+               cpb->hob_lbal = qc->tf.hob_lbal;
+               cpb->hob_lbam = qc->tf.hob_lbam;
+               cpb->hob_lbah = qc->tf.hob_lbah;
+       }
+
+       cpb->command = qc->tf.command;
+       /* don't load ctl - dunno why.  it's like that in the initio driver */
+
+       /* setup PRD for CDB */
+       if (is_atapi) {
+               memcpy(pkt->cdb, qc->cdb, ATAPI_CDB_LEN);
+               prd->mad = cpu_to_le32(pp->pkt_dma +
+                                      offsetof(struct inic_pkt, cdb));
+               prd->len = cpu_to_le16(cdb_len);
+               prd->flags = PRD_CDB | PRD_WRITE;
+               if (!is_data)
+                       prd->flags |= PRD_END;
+               prd++;
+       }
+
+       /* setup sg table */
+       if (is_data)
+               inic_fill_sg(prd, qc);
+
+       pp->cpb_tbl[0] = pp->pkt_dma;
+}
+
 static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
+       void __iomem *port_base = inic_port_base(ap);
 
-       /* ATA IRQ doesn't wait for DMA transfer completion and vice
-        * versa.  Mask IRQ selectively to detect command completion.
-        * Without it, ATA DMA read command can cause data corruption.
-        *
-        * Something similar might be needed for ATAPI writes.  I
-        * tried a lot of combinations but couldn't find the solution.
-        */
-       if (qc->tf.protocol == ATA_PROT_DMA &&
-           !(qc->tf.flags & ATA_TFLAG_WRITE))
-               inic_set_pirq_mask(ap, PIRQ_MASK_DMA_READ);
-       else
-               inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+       /* fire up the ADMA engine */
+       writew(HCTL_FTHD0, port_base + HOST_CTL);
+       writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
+       writeb(0, port_base + PORT_CPB_PTQFIFO);
+
+       return 0;
+}
+
+static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       void __iomem *port_base = inic_port_base(ap);
+
+       tf->feature     = readb(port_base + PORT_TF_FEATURE);
+       tf->nsect       = readb(port_base + PORT_TF_NSECT);
+       tf->lbal        = readb(port_base + PORT_TF_LBAL);
+       tf->lbam        = readb(port_base + PORT_TF_LBAM);
+       tf->lbah        = readb(port_base + PORT_TF_LBAH);
+       tf->device      = readb(port_base + PORT_TF_DEVICE);
+       tf->command     = readb(port_base + PORT_TF_COMMAND);
+}
 
-       /* Issuing a command to yet uninitialized port locks up the
-        * controller.  Most of the time, this happens for the first
-        * command after reset which are ATA and ATAPI IDENTIFYs.
-        * Fast fail if stat is 0x7f or 0xff for those commands.
+static bool inic_qc_fill_rtf(struct ata_queued_cmd *qc)
+{
+       struct ata_taskfile *rtf = &qc->result_tf;
+       struct ata_taskfile tf;
+
+       /* FIXME: Except for status and error, result TF access
+        * doesn't work.  I tried reading from BAR0/2, CPB and BAR5.
+        * None works regardless of which command interface is used.
+        * For now return true iff status indicates device error.
+        * This means that we're reporting bogus sector for RW
+        * failures.  Eeekk....
         */
-       if (unlikely(qc->tf.command == ATA_CMD_ID_ATA ||
-                    qc->tf.command == ATA_CMD_ID_ATAPI)) {
-               u8 stat = ap->ops->sff_check_status(ap);
-               if (stat == 0x7f || stat == 0xff)
-                       return AC_ERR_HSM;
-       }
+       inic_tf_read(qc->ap, &tf);
 
-       return ata_sff_qc_issue(qc);
+       if (!(tf.command & ATA_ERR))
+               return false;
+
+       rtf->command = tf.command;
+       rtf->feature = tf.feature;
+       return true;
 }
 
 static void inic_freeze(struct ata_port *ap)
 {
        void __iomem *port_base = inic_port_base(ap);
 
-       __inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);
-
-       ap->ops->sff_check_status(ap);
+       writeb(PIRQ_MASK_FREEZE, port_base + PORT_IRQ_MASK);
        writeb(0xff, port_base + PORT_IRQ_STAT);
-
-       readb(port_base + PORT_IRQ_STAT); /* flush */
 }
 
 static void inic_thaw(struct ata_port *ap)
 {
        void __iomem *port_base = inic_port_base(ap);
 
-       ap->ops->sff_check_status(ap);
        writeb(0xff, port_base + PORT_IRQ_STAT);
+       writeb(PIRQ_MASK_DEFAULT, port_base + PORT_IRQ_MASK);
+}
 
-       __inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+static int inic_check_ready(struct ata_link *link)
+{
+       void __iomem *port_base = inic_port_base(link->ap);
 
-       readb(port_base + PORT_IRQ_STAT); /* flush */
+       return ata_check_ready(readb(port_base + PORT_TF_COMMAND));
 }
 
 /*
@@ -394,17 +616,15 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
        void __iomem *port_base = inic_port_base(ap);
        void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
        const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-       u16 val;
        int rc;
 
        /* hammer it into sane state */
        inic_reset_port(port_base);
 
-       val = readw(idma_ctl);
-       writew(val | IDMA_CTL_RST_ATA, idma_ctl);
+       writew(IDMA_CTL_RST_ATA, idma_ctl);
        readw(idma_ctl);        /* flush */
        msleep(1);
-       writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);
+       writew(0, idma_ctl);
 
        rc = sata_link_resume(link, timing, deadline);
        if (rc) {
@@ -418,7 +638,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
                struct ata_taskfile tf;
 
                /* wait for link to become ready */
-               rc = ata_sff_wait_after_reset(link, 1, deadline);
+               rc = ata_wait_after_reset(link, deadline, inic_check_ready);
                /* link occupied, -ENODEV too is an error */
                if (rc) {
                        ata_link_printk(link, KERN_WARNING, "device not ready "
@@ -426,7 +646,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
                        return rc;
                }
 
-               ata_sff_tf_read(ap, &tf);
+               inic_tf_read(ap, &tf);
                *class = ata_dev_classify(&tf);
        }
 
@@ -436,18 +656,8 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
 static void inic_error_handler(struct ata_port *ap)
 {
        void __iomem *port_base = inic_port_base(ap);
-       struct inic_port_priv *pp = ap->private_data;
-       unsigned long flags;
 
-       /* reset PIO HSM and stop DMA engine */
        inic_reset_port(port_base);
-
-       spin_lock_irqsave(ap->lock, flags);
-       ap->hsm_task_state = HSM_ST_IDLE;
-       writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL);
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       /* PIO and DMA engines have been stopped, perform recovery */
        ata_std_error_handler(ap);
 }
 
@@ -458,26 +668,18 @@ static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
                inic_reset_port(inic_port_base(qc->ap));
 }
 
-static void inic_dev_config(struct ata_device *dev)
-{
-       /* inic can only handle upto LBA28 max sectors */
-       if (dev->max_sectors > ATA_MAX_SECTORS)
-               dev->max_sectors = ATA_MAX_SECTORS;
-
-       if (dev->n_sectors >= 1 << 28) {
-               ata_dev_printk(dev, KERN_ERR,
-       "ERROR: This driver doesn't support LBA48 yet and may cause\n"
-       "                data corruption on such devices.  Disabling.\n");
-               ata_dev_disable(dev);
-       }
-}
-
 static void init_port(struct ata_port *ap)
 {
        void __iomem *port_base = inic_port_base(ap);
+       struct inic_port_priv *pp = ap->private_data;
 
-       /* Setup PRD address */
+       /* clear packet and CPB table */
+       memset(pp->pkt, 0, sizeof(struct inic_pkt));
+       memset(pp->cpb_tbl, 0, IDMA_CPB_TBL_SIZE);
+
+       /* setup PRD and CPB lookup table addresses */
        writel(ap->prd_dma, port_base + PORT_PRD_ADDR);
+       writel(pp->cpb_tbl_dma, port_base + PORT_CPB_CPBLAR);
 }
 
 static int inic_port_resume(struct ata_port *ap)
@@ -488,28 +690,30 @@ static int inic_port_resume(struct ata_port *ap)
 
 static int inic_port_start(struct ata_port *ap)
 {
-       void __iomem *port_base = inic_port_base(ap);
+       struct device *dev = ap->host->dev;
        struct inic_port_priv *pp;
-       u8 tmp;
        int rc;
 
        /* alloc and initialize private data */
-       pp = devm_kzalloc(ap->host->dev, sizeof(*pp), GFP_KERNEL);
+       pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
        if (!pp)
                return -ENOMEM;
        ap->private_data = pp;
 
-       /* default PRD_CTL value, DMAEN, WR and START off */
-       tmp = readb(port_base + PORT_PRD_CTL);
-       tmp &= ~(PRD_CTL_DMAEN | PRD_CTL_WR | PRD_CTL_START);
-       pp->dfl_prdctl = tmp;
-
        /* Alloc resources */
        rc = ata_port_start(ap);
-       if (rc) {
-               kfree(pp);
+       if (rc)
                return rc;
-       }
+
+       pp->pkt = dmam_alloc_coherent(dev, sizeof(struct inic_pkt),
+                                     &pp->pkt_dma, GFP_KERNEL);
+       if (!pp->pkt)
+               return -ENOMEM;
+
+       pp->cpb_tbl = dmam_alloc_coherent(dev, IDMA_CPB_TBL_SIZE,
+                                         &pp->cpb_tbl_dma, GFP_KERNEL);
+       if (!pp->cpb_tbl)
+               return -ENOMEM;
 
        init_port(ap);
 
@@ -517,21 +721,18 @@ static int inic_port_start(struct ata_port *ap)
 }
 
 static struct ata_port_operations inic_port_ops = {
-       .inherits               = &ata_sff_port_ops,
+       .inherits               = &sata_port_ops,
 
-       .bmdma_setup            = inic_bmdma_setup,
-       .bmdma_start            = inic_bmdma_start,
-       .bmdma_stop             = inic_bmdma_stop,
-       .bmdma_status           = inic_bmdma_status,
+       .check_atapi_dma        = inic_check_atapi_dma,
+       .qc_prep                = inic_qc_prep,
        .qc_issue               = inic_qc_issue,
+       .qc_fill_rtf            = inic_qc_fill_rtf,
 
        .freeze                 = inic_freeze,
        .thaw                   = inic_thaw,
-       .softreset              = ATA_OP_NULL,  /* softreset is broken */
        .hardreset              = inic_hardreset,
        .error_handler          = inic_error_handler,
        .post_internal_cmd      = inic_post_internal_cmd,
-       .dev_config             = inic_dev_config,
 
        .scr_read               = inic_scr_read,
        .scr_write              = inic_scr_write,
@@ -541,12 +742,6 @@ static struct ata_port_operations inic_port_ops = {
 };
 
 static struct ata_port_info inic_port_info = {
-       /* For some reason, ATAPI_PROT_PIO is broken on this
-        * controller, and no, PIO_POLLING does't fix it.  It somehow
-        * manages to report the wrong ireason and ignoring ireason
-        * results in machine lock up.  Tell libata to always prefer
-        * DMA.
-        */
        .flags                  = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
        .pio_mask               = 0x1f, /* pio0-4 */
        .mwdma_mask             = 0x07, /* mwdma0-2 */
@@ -599,7 +794,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
        struct inic_host_priv *hpriv = host->private_data;
-       void __iomem *mmio_base = host->iomap[MMIO_BAR];
        int rc;
 
        rc = ata_pci_device_do_resume(pdev);
@@ -607,7 +801,7 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
                return rc;
 
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               rc = init_controller(mmio_base, hpriv->cached_hctl);
+               rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
                if (rc)
                        return rc;
        }
@@ -625,6 +819,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ata_host *host;
        struct inic_host_priv *hpriv;
        void __iomem * const *iomap;
+       int mmio_bar;
        int i, rc;
 
        if (!printed_version++)
@@ -638,38 +833,31 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        host->private_data = hpriv;
 
-       /* acquire resources and fill host */
+       /* Acquire resources and fill host.  Note that PCI and cardbus
+        * use different BARs.
+        */
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;
 
-       rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
+       if (pci_resource_flags(pdev, MMIO_BAR_PCI) & IORESOURCE_MEM)
+               mmio_bar = MMIO_BAR_PCI;
+       else
+               mmio_bar = MMIO_BAR_CARDBUS;
+
+       rc = pcim_iomap_regions(pdev, 1 << mmio_bar, DRV_NAME);
        if (rc)
                return rc;
        host->iomap = iomap = pcim_iomap_table(pdev);
+       hpriv->mmio_base = iomap[mmio_bar];
+       hpriv->cached_hctl = readw(hpriv->mmio_base + HOST_CTL);
 
        for (i = 0; i < NR_PORTS; i++) {
                struct ata_port *ap = host->ports[i];
-               struct ata_ioports *port = &ap->ioaddr;
-               unsigned int offset = i * PORT_SIZE;
-
-               port->cmd_addr = iomap[2 * i];
-               port->altstatus_addr =
-               port->ctl_addr = (void __iomem *)
-                       ((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);
-               port->scr_addr = iomap[MMIO_BAR] + offset + PORT_SCR;
-
-               ata_sff_std_ports(port);
-
-               ata_port_pbar_desc(ap, MMIO_BAR, -1, "mmio");
-               ata_port_pbar_desc(ap, MMIO_BAR, offset, "port");
-               ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
-                 (unsigned long long)pci_resource_start(pdev, 2 * i),
-                 (unsigned long long)pci_resource_start(pdev, (2 * i + 1)) |
-                                     ATA_PCI_CTL_OFS);
-       }
 
-       hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL);
+               ata_port_pbar_desc(ap, mmio_bar, -1, "mmio");
+               ata_port_pbar_desc(ap, mmio_bar, i * PORT_SIZE, "port");
+       }
 
        /* Set dma_mask.  This devices doesn't support 64bit addressing. */
        rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
@@ -698,7 +886,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
-       rc = init_controller(iomap[MMIO_BAR], hpriv->cached_hctl);
+       rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
        if (rc) {
                dev_printk(KERN_ERR, &pdev->dev,
                           "failed to initialize controller\n");
index 842b1a15b78cadfafb5e031a8fe57245e6045380..bb73b2222627b9b6a05f96057da351c7d417f935 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 #include <linux/mbus.h>
+#include <linux/bitops.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -91,9 +92,9 @@ enum {
        MV_IRQ_COAL_TIME_THRESHOLD      = (MV_IRQ_COAL_REG_BASE + 0xd0),
 
        MV_SATAHC0_REG_BASE     = 0x20000,
-       MV_FLASH_CTL            = 0x1046c,
-       MV_GPIO_PORT_CTL        = 0x104f0,
-       MV_RESET_CFG            = 0x180d8,
+       MV_FLASH_CTL_OFS        = 0x1046c,
+       MV_GPIO_PORT_CTL_OFS    = 0x104f0,
+       MV_RESET_CFG_OFS        = 0x180d8,
 
        MV_PCI_REG_SZ           = MV_MAJOR_REG_AREA_SZ,
        MV_SATAHC_REG_SZ        = MV_MAJOR_REG_AREA_SZ,
@@ -147,18 +148,21 @@ enum {
        /* PCI interface registers */
 
        PCI_COMMAND_OFS         = 0xc00,
+       PCI_COMMAND_MRDTRIG     = (1 << 7),     /* PCI Master Read Trigger */
 
        PCI_MAIN_CMD_STS_OFS    = 0xd30,
        STOP_PCI_MASTER         = (1 << 2),
        PCI_MASTER_EMPTY        = (1 << 3),
        GLOB_SFT_RST            = (1 << 4),
 
-       MV_PCI_MODE             = 0xd00,
+       MV_PCI_MODE_OFS         = 0xd00,
+       MV_PCI_MODE_MASK        = 0x30,
+
        MV_PCI_EXP_ROM_BAR_CTL  = 0xd2c,
        MV_PCI_DISC_TIMER       = 0xd04,
        MV_PCI_MSI_TRIGGER      = 0xc38,
        MV_PCI_SERR_MASK        = 0xc28,
-       MV_PCI_XBAR_TMOUT       = 0x1d04,
+       MV_PCI_XBAR_TMOUT_OFS   = 0x1d04,
        MV_PCI_ERR_LOW_ADDRESS  = 0x1d40,
        MV_PCI_ERR_HIGH_ADDRESS = 0x1d44,
        MV_PCI_ERR_ATTRIBUTE    = 0x1d48,
@@ -225,16 +229,18 @@ enum {
        PHY_MODE4               = 0x314,
        PHY_MODE2               = 0x330,
        SATA_IFCTL_OFS          = 0x344,
+       SATA_TESTCTL_OFS        = 0x348,
        SATA_IFSTAT_OFS         = 0x34c,
        VENDOR_UNIQUE_FIS_OFS   = 0x35c,
 
-       FIS_CFG_OFS             = 0x360,
-       FIS_CFG_SINGLE_SYNC     = (1 << 16),    /* SYNC on DMA activation */
+       FISCFG_OFS              = 0x360,
+       FISCFG_WAIT_DEV_ERR     = (1 << 8),     /* wait for host on DevErr */
+       FISCFG_SINGLE_SYNC      = (1 << 16),    /* SYNC on DMA activation */
 
        MV5_PHY_MODE            = 0x74,
-       MV5_LT_MODE             = 0x30,
-       MV5_PHY_CTL             = 0x0C,
-       SATA_INTERFACE_CFG      = 0x050,
+       MV5_LTMODE_OFS          = 0x30,
+       MV5_PHY_CTL_OFS         = 0x0C,
+       SATA_INTERFACE_CFG_OFS  = 0x050,
 
        MV_M2_PREAMP_MASK       = 0x7e0,
 
@@ -332,10 +338,16 @@ enum {
        EDMA_CMD_OFS            = 0x28,         /* EDMA command register */
        EDMA_EN                 = (1 << 0),     /* enable EDMA */
        EDMA_DS                 = (1 << 1),     /* disable EDMA; self-negated */
-       ATA_RST                 = (1 << 2),     /* reset trans/link/phy */
+       EDMA_RESET              = (1 << 2),     /* reset eng/trans/link/phy */
+
+       EDMA_STATUS_OFS         = 0x30,         /* EDMA engine status */
+       EDMA_STATUS_CACHE_EMPTY = (1 << 6),     /* GenIIe command cache empty */
+       EDMA_STATUS_IDLE        = (1 << 7),     /* GenIIe EDMA enabled/idle */
 
-       EDMA_IORDY_TMOUT        = 0x34,
-       EDMA_ARB_CFG            = 0x38,
+       EDMA_IORDY_TMOUT_OFS    = 0x34,
+       EDMA_ARB_CFG_OFS        = 0x38,
+
+       EDMA_HALTCOND_OFS       = 0x60,         /* GenIIe halt conditions */
 
        GEN_II_NCQ_MAX_SECTORS  = 256,          /* max sects/io on Gen2 w/NCQ */
 
@@ -350,15 +362,19 @@ enum {
        MV_HP_GEN_II            = (1 << 7),     /* Generation II: 60xx */
        MV_HP_GEN_IIE           = (1 << 8),     /* Generation IIE: 6042/7042 */
        MV_HP_PCIE              = (1 << 9),     /* PCIe bus/regs: 7042 */
+       MV_HP_CUT_THROUGH       = (1 << 10),    /* can use EDMA cut-through */
 
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),     /* is EDMA engine enabled? */
        MV_PP_FLAG_NCQ_EN       = (1 << 1),     /* is EDMA set up for NCQ? */
+       MV_PP_FLAG_FBS_EN       = (1 << 2),     /* is EDMA set up for FBS? */
+       MV_PP_FLAG_DELAYED_EH   = (1 << 3),     /* delayed dev err handling */
 };
 
 #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
 #define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
 #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
+#define IS_PCIE(hpriv) ((hpriv)->hp_flags & MV_HP_PCIE)
 #define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
 
 #define WINDOW_CTRL(i)         (0x20030 + ((i) << 4))
@@ -433,6 +449,7 @@ struct mv_port_priv {
        unsigned int            resp_idx;
 
        u32                     pp_flags;
+       unsigned int            delayed_eh_pmp_map;
 };
 
 struct mv_port_signal {
@@ -479,6 +496,7 @@ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
 static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
+static int mv_qc_defer(struct ata_queued_cmd *qc);
 static void mv_qc_prep(struct ata_queued_cmd *qc);
 static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
@@ -527,6 +545,9 @@ static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
                                unsigned long deadline);
 static int  mv_softreset(struct ata_link *link, unsigned int *class,
                                unsigned long deadline);
+static void mv_pmp_error_handler(struct ata_port *ap);
+static void mv_process_crpb_entries(struct ata_port *ap,
+                                       struct mv_port_priv *pp);
 
 /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
  * because we have to allow room for worst case splitting of
@@ -548,6 +569,7 @@ static struct scsi_host_template mv6_sht = {
 static struct ata_port_operations mv5_ops = {
        .inherits               = &ata_sff_port_ops,
 
+       .qc_defer               = mv_qc_defer,
        .qc_prep                = mv_qc_prep,
        .qc_issue               = mv_qc_issue,
 
@@ -566,7 +588,6 @@ static struct ata_port_operations mv5_ops = {
 
 static struct ata_port_operations mv6_ops = {
        .inherits               = &mv5_ops,
-       .qc_defer               = sata_pmp_qc_defer_cmd_switch,
        .dev_config             = mv6_dev_config,
        .scr_read               = mv_scr_read,
        .scr_write              = mv_scr_write,
@@ -574,12 +595,11 @@ static struct ata_port_operations mv6_ops = {
        .pmp_hardreset          = mv_pmp_hardreset,
        .pmp_softreset          = mv_softreset,
        .softreset              = mv_softreset,
-       .error_handler          = sata_pmp_error_handler,
+       .error_handler          = mv_pmp_error_handler,
 };
 
 static struct ata_port_operations mv_iie_ops = {
        .inherits               = &mv6_ops,
-       .qc_defer               = ata_std_qc_defer, /* FIS-based switching */
        .dev_config             = ATA_OP_NULL,
        .qc_prep                = mv_qc_prep_iie,
 };
@@ -875,6 +895,29 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
        }
 }
 
+static void mv_wait_for_edma_empty_idle(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       const u32 empty_idle = (EDMA_STATUS_CACHE_EMPTY | EDMA_STATUS_IDLE);
+       const int per_loop = 5, timeout = (15 * 1000 / per_loop);
+       int i;
+
+       /*
+        * Wait for the EDMA engine to finish transactions in progress.
+        * No idea what a good "timeout" value might be, but measurements
+        * indicate that it often requires hundreds of microseconds
+        * with two drives in-use.  So we use the 15msec value above
+        * as a rough guess at what even more drives might require.
+        */
+       for (i = 0; i < timeout; ++i) {
+               u32 edma_stat = readl(port_mmio + EDMA_STATUS_OFS);
+               if ((edma_stat & empty_idle) == empty_idle)
+                       break;
+               udelay(per_loop);
+       }
+       /* ata_port_printk(ap, KERN_INFO, "%s: %u+ usecs\n", __func__, i); */
+}
+
 /**
  *      mv_stop_edma_engine - Disable eDMA engine
  *      @port_mmio: io base address
@@ -907,6 +950,7 @@ static int mv_stop_edma(struct ata_port *ap)
        if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
                return 0;
        pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+       mv_wait_for_edma_empty_idle(ap);
        if (mv_stop_edma_engine(port_mmio)) {
                ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
                return -EIO;
@@ -1057,26 +1101,95 @@ static void mv6_dev_config(struct ata_device *adev)
        }
 }
 
-static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs)
+static int mv_qc_defer(struct ata_queued_cmd *qc)
 {
-       u32 old_fcfg, new_fcfg, old_ltmode, new_ltmode;
+       struct ata_link *link = qc->dev->link;
+       struct ata_port *ap = link->ap;
+       struct mv_port_priv *pp = ap->private_data;
+
+       /*
+        * Don't allow new commands if we're in a delayed EH state
+        * for NCQ and/or FIS-based switching.
+        */
+       if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH)
+               return ATA_DEFER_PORT;
        /*
-        * Various bit settings required for operation
-        * in FIS-based switching (fbs) mode on GenIIe:
+        * If the port is completely idle, then allow the new qc.
         */
-       old_fcfg   = readl(port_mmio + FIS_CFG_OFS);
-       old_ltmode = readl(port_mmio + LTMODE_OFS);
-       if (enable_fbs) {
-               new_fcfg   = old_fcfg   |  FIS_CFG_SINGLE_SYNC;
-               new_ltmode = old_ltmode |  LTMODE_BIT8;
-       } else { /* disable fbs */
-               new_fcfg   = old_fcfg   & ~FIS_CFG_SINGLE_SYNC;
-               new_ltmode = old_ltmode & ~LTMODE_BIT8;
-       }
-       if (new_fcfg != old_fcfg)
-               writelfl(new_fcfg, port_mmio + FIS_CFG_OFS);
+       if (ap->nr_active_links == 0)
+               return 0;
+
+       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+               /*
+                * The port is operating in host queuing mode (EDMA).
+                * It can accomodate a new qc if the qc protocol
+                * is compatible with the current host queue mode.
+                */
+               if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) {
+                       /*
+                        * The host queue (EDMA) is in NCQ mode.
+                        * If the new qc is also an NCQ command,
+                        * then allow the new qc.
+                        */
+                       if (qc->tf.protocol == ATA_PROT_NCQ)
+                               return 0;
+               } else {
+                       /*
+                        * The host queue (EDMA) is in non-NCQ, DMA mode.
+                        * If the new qc is also a non-NCQ, DMA command,
+                        * then allow the new qc.
+                        */
+                       if (qc->tf.protocol == ATA_PROT_DMA)
+                               return 0;
+               }
+       }
+       return ATA_DEFER_PORT;
+}
+
+static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs)
+{
+       u32 new_fiscfg, old_fiscfg;
+       u32 new_ltmode, old_ltmode;
+       u32 new_haltcond, old_haltcond;
+
+       old_fiscfg   = readl(port_mmio + FISCFG_OFS);
+       old_ltmode   = readl(port_mmio + LTMODE_OFS);
+       old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+
+       new_fiscfg   = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
+       new_ltmode   = old_ltmode & ~LTMODE_BIT8;
+       new_haltcond = old_haltcond | EDMA_ERR_DEV;
+
+       if (want_fbs) {
+               new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC;
+               new_ltmode = old_ltmode | LTMODE_BIT8;
+               if (want_ncq)
+                       new_haltcond &= ~EDMA_ERR_DEV;
+               else
+                       new_fiscfg |=  FISCFG_WAIT_DEV_ERR;
+       }
+
+       if (new_fiscfg != old_fiscfg)
+               writelfl(new_fiscfg, port_mmio + FISCFG_OFS);
        if (new_ltmode != old_ltmode)
                writelfl(new_ltmode, port_mmio + LTMODE_OFS);
+       if (new_haltcond != old_haltcond)
+               writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS);
+}
+
+static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
+{
+       struct mv_host_priv *hpriv = ap->host->private_data;
+       u32 old, new;
+
+       /* workaround for 88SX60x1 FEr SATA#25 (part 1) */
+       old = readl(hpriv->base + MV_GPIO_PORT_CTL_OFS);
+       if (want_ncq)
+               new = old | (1 << 22);
+       else
+               new = old & ~(1 << 22);
+       if (new != old)
+               writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS);
 }
 
 static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
@@ -1088,25 +1201,40 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
 
        /* set up non-NCQ EDMA configuration */
        cfg = EDMA_CFG_Q_DEPTH;         /* always 0x1f for *all* chips */
+       pp->pp_flags &= ~MV_PP_FLAG_FBS_EN;
 
        if (IS_GEN_I(hpriv))
                cfg |= (1 << 8);        /* enab config burst size mask */
 
-       else if (IS_GEN_II(hpriv))
+       else if (IS_GEN_II(hpriv)) {
                cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
+               mv_60x1_errata_sata25(ap, want_ncq);
 
-       else if (IS_GEN_IIE(hpriv)) {
-               cfg |= (1 << 23);       /* do not mask PM field in rx'd FIS */
-               cfg |= (1 << 22);       /* enab 4-entry host queue cache */
-               cfg |= (1 << 18);       /* enab early completion */
-               cfg |= (1 << 17);       /* enab cut-through (dis stor&forwrd) */
+       } else if (IS_GEN_IIE(hpriv)) {
+               int want_fbs = sata_pmp_attached(ap);
+               /*
+                * Possible future enhancement:
+                *
+                * The chip can use FBS with non-NCQ, if we allow it,
+                * But first we need to have the error handling in place
+                * for this mode (datasheet section 7.3.15.4.2.3).
+                * So disallow non-NCQ FBS for now.
+                */
+               want_fbs &= want_ncq;
+
+               mv_config_fbs(port_mmio, want_ncq, want_fbs);
 
-               if (want_ncq && sata_pmp_attached(ap)) {
+               if (want_fbs) {
+                       pp->pp_flags |= MV_PP_FLAG_FBS_EN;
                        cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
-                       mv_config_fbs(port_mmio, 1);
-               } else {
-                       mv_config_fbs(port_mmio, 0);
                }
+
+               cfg |= (1 << 23);       /* do not mask PM field in rx'd FIS */
+               cfg |= (1 << 22);       /* enab 4-entry host queue cache */
+               if (HAS_PCI(ap->host))
+                       cfg |= (1 << 18);       /* enab early completion */
+               if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
+                       cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
        }
 
        if (want_ncq) {
@@ -1483,25 +1611,186 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
        return qc;
 }
 
-static void mv_unexpected_intr(struct ata_port *ap)
+static void mv_pmp_error_handler(struct ata_port *ap)
 {
+       unsigned int pmp, pmp_map;
        struct mv_port_priv *pp = ap->private_data;
-       struct ata_eh_info *ehi = &ap->link.eh_info;
-       char *when = "";
 
+       if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH) {
+               /*
+                * Perform NCQ error analysis on failed PMPs
+                * before we freeze the port entirely.
+                *
+                * The failed PMPs are marked earlier by mv_pmp_eh_prep().
+                */
+               pmp_map = pp->delayed_eh_pmp_map;
+               pp->pp_flags &= ~MV_PP_FLAG_DELAYED_EH;
+               for (pmp = 0; pmp_map != 0; pmp++) {
+                       unsigned int this_pmp = (1 << pmp);
+                       if (pmp_map & this_pmp) {
+                               struct ata_link *link = &ap->pmp_link[pmp];
+                               pmp_map &= ~this_pmp;
+                               ata_eh_analyze_ncq_error(link);
+                       }
+               }
+               ata_port_freeze(ap);
+       }
+       sata_pmp_error_handler(ap);
+}
+
+static unsigned int mv_get_err_pmp_map(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+
+       return readl(port_mmio + SATA_TESTCTL_OFS) >> 16;
+}
+
+static void mv_pmp_eh_prep(struct ata_port *ap, unsigned int pmp_map)
+{
+       struct ata_eh_info *ehi;
+       unsigned int pmp;
+
+       /*
+        * Initialize EH info for PMPs which saw device errors
+        */
+       ehi = &ap->link.eh_info;
+       for (pmp = 0; pmp_map != 0; pmp++) {
+               unsigned int this_pmp = (1 << pmp);
+               if (pmp_map & this_pmp) {
+                       struct ata_link *link = &ap->pmp_link[pmp];
+
+                       pmp_map &= ~this_pmp;
+                       ehi = &link->eh_info;
+                       ata_ehi_clear_desc(ehi);
+                       ata_ehi_push_desc(ehi, "dev err");
+                       ehi->err_mask |= AC_ERR_DEV;
+                       ehi->action |= ATA_EH_RESET;
+                       ata_link_abort(link);
+               }
+       }
+}
+
+static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)
+{
+       struct mv_port_priv *pp = ap->private_data;
+       int failed_links;
+       unsigned int old_map, new_map;
+
+       /*
+        * Device error during FBS+NCQ operation:
+        *
+        * Set a port flag to prevent further I/O being enqueued.
+        * Leave the EDMA running to drain outstanding commands from this port.
+        * Perform the post-mortem/EH only when all responses are complete.
+        * Follow recovery sequence from 6042/7042 datasheet (7.3.15.4.2.2).
+        */
+       if (!(pp->pp_flags & MV_PP_FLAG_DELAYED_EH)) {
+               pp->pp_flags |= MV_PP_FLAG_DELAYED_EH;
+               pp->delayed_eh_pmp_map = 0;
+       }
+       old_map = pp->delayed_eh_pmp_map;
+       new_map = old_map | mv_get_err_pmp_map(ap);
+
+       if (old_map != new_map) {
+               pp->delayed_eh_pmp_map = new_map;
+               mv_pmp_eh_prep(ap, new_map & ~old_map);
+       }
+       failed_links = hweight16(new_map);
+
+       ata_port_printk(ap, KERN_INFO, "%s: pmp_map=%04x qc_map=%04x "
+                       "failed_links=%d nr_active_links=%d\n",
+                       __func__, pp->delayed_eh_pmp_map,
+                       ap->qc_active, failed_links,
+                       ap->nr_active_links);
+
+       if (ap->nr_active_links <= failed_links) {
+               mv_process_crpb_entries(ap, pp);
+               mv_stop_edma(ap);
+               mv_eh_freeze(ap);
+               ata_port_printk(ap, KERN_INFO, "%s: done\n", __func__);
+               return 1;       /* handled */
+       }
+       ata_port_printk(ap, KERN_INFO, "%s: waiting\n", __func__);
+       return 1;       /* handled */
+}
+
+static int mv_handle_fbs_non_ncq_dev_err(struct ata_port *ap)
+{
        /*
-        * We got a device interrupt from something that
-        * was supposed to be using EDMA or polling.
+        * Possible future enhancement:
+        *
+        * FBS+non-NCQ operation is not yet implemented.
+        * See related notes in mv_edma_cfg().
+        *
+        * Device error during FBS+non-NCQ operation:
+        *
+        * We need to snapshot the shadow registers for each failed command.
+        * Follow recovery sequence from 6042/7042 datasheet (7.3.15.4.2.3).
         */
+       return 0;       /* not handled */
+}
+
+static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)
+{
+       struct mv_port_priv *pp = ap->private_data;
+
+       if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
+               return 0;       /* EDMA was not active: not handled */
+       if (!(pp->pp_flags & MV_PP_FLAG_FBS_EN))
+               return 0;       /* FBS was not active: not handled */
+
+       if (!(edma_err_cause & EDMA_ERR_DEV))
+               return 0;       /* non DEV error: not handled */
+       edma_err_cause &= ~EDMA_ERR_IRQ_TRANSIENT;
+       if (edma_err_cause & ~(EDMA_ERR_DEV | EDMA_ERR_SELF_DIS))
+               return 0;       /* other problems: not handled */
+
+       if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) {
+               /*
+                * EDMA should NOT have self-disabled for this case.
+                * If it did, then something is wrong elsewhere,
+                * and we cannot handle it here.
+                */
+               if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+                       ata_port_printk(ap, KERN_WARNING,
+                               "%s: err_cause=0x%x pp_flags=0x%x\n",
+                               __func__, edma_err_cause, pp->pp_flags);
+                       return 0; /* not handled */
+               }
+               return mv_handle_fbs_ncq_dev_err(ap);
+       } else {
+               /*
+                * EDMA should have self-disabled for this case.
+                * If it did not, then something is wrong elsewhere,
+                * and we cannot handle it here.
+                */
+               if (!(edma_err_cause & EDMA_ERR_SELF_DIS)) {
+                       ata_port_printk(ap, KERN_WARNING,
+                               "%s: err_cause=0x%x pp_flags=0x%x\n",
+                               __func__, edma_err_cause, pp->pp_flags);
+                       return 0; /* not handled */
+               }
+               return mv_handle_fbs_non_ncq_dev_err(ap);
+       }
+       return 0;       /* not handled */
+}
+
+static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled)
+{
+       struct ata_eh_info *ehi = &ap->link.eh_info;
+       char *when = "idle";
+
        ata_ehi_clear_desc(ehi);
-       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-               when = " while EDMA enabled";
+       if (!ap || (ap->flags & ATA_FLAG_DISABLED)) {
+               when = "disabled";
+       } else if (edma_was_enabled) {
+               when = "EDMA enabled";
        } else {
                struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
                if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
-                       when = " while polling";
+                       when = "polling";
        }
-       ata_ehi_push_desc(ehi, "unexpected device interrupt%s", when);
+       ata_ehi_push_desc(ehi, "unexpected device interrupt while %s", when);
        ehi->err_mask |= AC_ERR_OTHER;
        ehi->action   |= ATA_EH_RESET;
        ata_port_freeze(ap);
@@ -1519,7 +1808,7 @@ static void mv_unexpected_intr(struct ata_port *ap)
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+static void mv_err_intr(struct ata_port *ap)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
        u32 edma_err_cause, eh_freeze_mask, serr = 0;
@@ -1527,24 +1816,42 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        struct mv_host_priv *hpriv = ap->host->private_data;
        unsigned int action = 0, err_mask = 0;
        struct ata_eh_info *ehi = &ap->link.eh_info;
-
-       ata_ehi_clear_desc(ehi);
+       struct ata_queued_cmd *qc;
+       int abort = 0;
 
        /*
-        * Read and clear the err_cause bits.  This won't actually
-        * clear for some errors (eg. SError), but we will be doing
-        * a hard reset in those cases regardless, which *will* clear it.
+        * Read and clear the SError and err_cause bits.
         */
+       sata_scr_read(&ap->link, SCR_ERROR, &serr);
+       sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
+
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
        writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-       ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
+       ata_port_printk(ap, KERN_INFO, "%s: err_cause=%08x pp_flags=0x%x\n",
+                       __func__, edma_err_cause, pp->pp_flags);
+
+       if (edma_err_cause & EDMA_ERR_DEV) {
+               /*
+                * Device errors during FIS-based switching operation
+                * require special handling.
+                */
+               if (mv_handle_dev_err(ap, edma_err_cause))
+                       return;
+       }
 
+       qc = mv_get_active_qc(ap);
+       ata_ehi_clear_desc(ehi);
+       ata_ehi_push_desc(ehi, "edma_err_cause=%08x pp_flags=%08x",
+                         edma_err_cause, pp->pp_flags);
        /*
         * All generations share these EDMA error cause bits:
         */
-       if (edma_err_cause & EDMA_ERR_DEV)
+       if (edma_err_cause & EDMA_ERR_DEV) {
                err_mask |= AC_ERR_DEV;
+               action |= ATA_EH_RESET;
+               ata_ehi_push_desc(ehi, "dev error");
+       }
        if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
                        EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
                        EDMA_ERR_INTRL_PAR)) {
@@ -1576,13 +1883,6 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                        ata_ehi_push_desc(ehi, "EDMA self-disable");
                }
                if (edma_err_cause & EDMA_ERR_SERR) {
-                       /*
-                        * Ensure that we read our own SCR, not a pmp link SCR:
-                        */
-                       ap->ops->scr_read(ap, SCR_ERROR, &serr);
-                       /*
-                        * Don't clear SError here; leave it for libata-eh:
-                        */
                        ata_ehi_push_desc(ehi, "SError=%08x", serr);
                        err_mask |= AC_ERR_ATA_BUS;
                        action |= ATA_EH_RESET;
@@ -1602,10 +1902,29 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        else
                ehi->err_mask |= err_mask;
 
-       if (edma_err_cause & eh_freeze_mask)
+       if (err_mask == AC_ERR_DEV) {
+               /*
+                * Cannot do ata_port_freeze() here,
+                * because it would kill PIO access,
+                * which is needed for further diagnosis.
+                */
+               mv_eh_freeze(ap);
+               abort = 1;
+       } else if (edma_err_cause & eh_freeze_mask) {
+               /*
+                * Note to self: ata_port_freeze() calls ata_port_abort()
+                */
                ata_port_freeze(ap);
-       else
-               ata_port_abort(ap);
+       } else {
+               abort = 1;
+       }
+
+       if (abort) {
+               if (qc)
+                       ata_link_abort(qc->dev->link);
+               else
+                       ata_port_abort(ap);
+       }
 }
 
 static void mv_process_crpb_response(struct ata_port *ap,
@@ -1632,8 +1951,9 @@ static void mv_process_crpb_response(struct ata_port *ap,
                        }
                }
                ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
-               qc->err_mask |= ac_err_mask(ata_status);
-               ata_qc_complete(qc);
+               if (!ac_err_mask(ata_status))
+                       ata_qc_complete(qc);
+               /* else: leave it for mv_err_intr() */
        } else {
                ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
                                __func__, tag);
@@ -1677,6 +1997,44 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
                         port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
 
+static void mv_port_intr(struct ata_port *ap, u32 port_cause)
+{
+       struct mv_port_priv *pp;
+       int edma_was_enabled;
+
+       if (!ap || (ap->flags & ATA_FLAG_DISABLED)) {
+               mv_unexpected_intr(ap, 0);
+               return;
+       }
+       /*
+        * Grab a snapshot of the EDMA_EN flag setting,
+        * so that we have a consistent view for this port,
+        * even if something we call of our routines changes it.
+        */
+       pp = ap->private_data;
+       edma_was_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+       /*
+        * Process completed CRPB response(s) before other events.
+        */
+       if (edma_was_enabled && (port_cause & DONE_IRQ)) {
+               mv_process_crpb_entries(ap, pp);
+               if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH)
+                       mv_handle_fbs_ncq_dev_err(ap);
+       }
+       /*
+        * Handle chip-reported errors, or continue on to handle PIO.
+        */
+       if (unlikely(port_cause & ERR_IRQ)) {
+               mv_err_intr(ap);
+       } else if (!edma_was_enabled) {
+               struct ata_queued_cmd *qc = mv_get_active_qc(ap);
+               if (qc)
+                       ata_sff_host_intr(ap, qc);
+               else
+                       mv_unexpected_intr(ap, edma_was_enabled);
+       }
+}
+
 /**
  *      mv_host_intr - Handle all interrupts on the given host controller
  *      @host: host specific structure
@@ -1688,66 +2046,58 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
 static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
 {
        struct mv_host_priv *hpriv = host->private_data;
-       void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
-       u32 hc_irq_cause = 0;
+       void __iomem *mmio = hpriv->base, *hc_mmio;
        unsigned int handled = 0, port;
 
        for (port = 0; port < hpriv->n_ports; port++) {
                struct ata_port *ap = host->ports[port];
-               struct mv_port_priv *pp;
-               unsigned int shift, hardport, port_cause;
-               /*
-                * When we move to the second hc, flag our cached
-                * copies of hc_mmio (and hc_irq_cause) as invalid again.
-                */
-               if (port == MV_PORTS_PER_HC)
-                       hc_mmio = NULL;
-               /*
-                * Do nothing if port is not interrupting or is disabled:
-                */
+               unsigned int p, shift, hardport, port_cause;
+
                MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
-               port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
-               if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
-                       continue;
                /*
-                * Each hc within the host has its own hc_irq_cause register.
-                * We defer reading it until we know we need it, right now:
-                *
-                * FIXME later: we don't really need to read this register
-                * (some logic changes required below if we go that way),
-                * because it doesn't tell us anything new.  But we do need
-                * to write to it, outside the top of this loop,
-                * to reset the interrupt triggers for next time.
+                * Each hc within the host has its own hc_irq_cause register,
+                * where the interrupting ports bits get ack'd.
                 */
-               if (!hc_mmio) {
+               if (hardport == 0) {    /* first port on this hc ? */
+                       u32 hc_cause = (main_irq_cause >> shift) & HC0_IRQ_PEND;
+                       u32 port_mask, ack_irqs;
+                       /*
+                        * Skip this entire hc if nothing pending for any ports
+                        */
+                       if (!hc_cause) {
+                               port += MV_PORTS_PER_HC - 1;
+                               continue;
+                       }
+                       /*
+                        * We don't need/want to read the hc_irq_cause register,
+                        * because doing so hurts performance, and
+                        * main_irq_cause already gives us everything we need.
+                        *
+                        * But we do have to *write* to the hc_irq_cause to ack
+                        * the ports that we are handling this time through.
+                        *
+                        * This requires that we create a bitmap for those
+                        * ports which interrupted us, and use that bitmap
+                        * to ack (only) those ports via hc_irq_cause.
+                        */
+                       ack_irqs = 0;
+                       for (p = 0; p < MV_PORTS_PER_HC; ++p) {
+                               if ((port + p) >= hpriv->n_ports)
+                                       break;
+                               port_mask = (DONE_IRQ | ERR_IRQ) << (p * 2);
+                               if (hc_cause & port_mask)
+                                       ack_irqs |= (DMA_IRQ | DEV_IRQ) << p;
+                       }
                        hc_mmio = mv_hc_base_from_port(mmio, port);
-                       hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-                       writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+                       writelfl(~ack_irqs, hc_mmio + HC_IRQ_CAUSE_OFS);
                        handled = 1;
                }
                /*
-                * Process completed CRPB response(s) before other events.
-                */
-               pp = ap->private_data;
-               if (hc_irq_cause & (DMA_IRQ << hardport)) {
-                       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN)
-                               mv_process_crpb_entries(ap, pp);
-               }
-               /*
-                * Handle chip-reported errors, or continue on to handle PIO.
+                * Handle interrupts signalled for this port:
                 */
-               if (unlikely(port_cause & ERR_IRQ)) {
-                       mv_err_intr(ap, mv_get_active_qc(ap));
-               } else if (hc_irq_cause & (DEV_IRQ << hardport)) {
-                       if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
-                               struct ata_queued_cmd *qc = mv_get_active_qc(ap);
-                               if (qc) {
-                                       ata_sff_host_intr(ap, qc);
-                                       continue;
-                               }
-                       }
-                       mv_unexpected_intr(ap);
-               }
+               port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
+               if (port_cause)
+                       mv_port_intr(ap, port_cause);
        }
        return handled;
 }
@@ -1894,7 +2244,7 @@ static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio)
 
 static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
 {
-       writel(0x0fcfffff, mmio + MV_FLASH_CTL);
+       writel(0x0fcfffff, mmio + MV_FLASH_CTL_OFS);
 }
 
 static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
@@ -1913,7 +2263,7 @@ static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
 {
        u32 tmp;
 
-       writel(0, mmio + MV_GPIO_PORT_CTL);
+       writel(0, mmio + MV_GPIO_PORT_CTL_OFS);
 
        /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
 
@@ -1931,14 +2281,14 @@ static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
        int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
 
        if (fix_apm_sq) {
-               tmp = readl(phy_mmio + MV5_LT_MODE);
+               tmp = readl(phy_mmio + MV5_LTMODE_OFS);
                tmp |= (1 << 19);
-               writel(tmp, phy_mmio + MV5_LT_MODE);
+               writel(tmp, phy_mmio + MV5_LTMODE_OFS);
 
-               tmp = readl(phy_mmio + MV5_PHY_CTL);
+               tmp = readl(phy_mmio + MV5_PHY_CTL_OFS);
                tmp &= ~0x3;
                tmp |= 0x1;
-               writel(tmp, phy_mmio + MV5_PHY_CTL);
+               writel(tmp, phy_mmio + MV5_PHY_CTL_OFS);
        }
 
        tmp = readl(phy_mmio + MV5_PHY_MODE);
@@ -1956,11 +2306,6 @@ static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
 {
        void __iomem *port_mmio = mv_port_base(mmio, port);
 
-       /*
-        * The datasheet warns against setting ATA_RST when EDMA is active
-        * (but doesn't say what the problem might be).  So we first try
-        * to disable the EDMA engine before doing the ATA_RST operation.
-        */
        mv_reset_channel(hpriv, mmio, port);
 
        ZERO(0x028);    /* command */
@@ -1975,7 +2320,7 @@ static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
        ZERO(0x024);    /* respq outp */
        ZERO(0x020);    /* respq inp */
        ZERO(0x02c);    /* test control */
-       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
+       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT_OFS);
 }
 #undef ZERO
 
@@ -2021,13 +2366,13 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
        struct mv_host_priv *hpriv = host->private_data;
        u32 tmp;
 
-       tmp = readl(mmio + MV_PCI_MODE);
+       tmp = readl(mmio + MV_PCI_MODE_OFS);
        tmp &= 0xff00ffff;
-       writel(tmp, mmio + MV_PCI_MODE);
+       writel(tmp, mmio + MV_PCI_MODE_OFS);
 
        ZERO(MV_PCI_DISC_TIMER);
        ZERO(MV_PCI_MSI_TRIGGER);
-       writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
+       writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS);
        ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
        ZERO(MV_PCI_SERR_MASK);
        ZERO(hpriv->irq_cause_ofs);
@@ -2045,10 +2390,10 @@ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
 
        mv5_reset_flash(hpriv, mmio);
 
-       tmp = readl(mmio + MV_GPIO_PORT_CTL);
+       tmp = readl(mmio + MV_GPIO_PORT_CTL_OFS);
        tmp &= 0x3;
        tmp |= (1 << 5) | (1 << 6);
-       writel(tmp, mmio + MV_GPIO_PORT_CTL);
+       writel(tmp, mmio + MV_GPIO_PORT_CTL_OFS);
 }
 
 /**
@@ -2121,7 +2466,7 @@ static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
        void __iomem *port_mmio;
        u32 tmp;
 
-       tmp = readl(mmio + MV_RESET_CFG);
+       tmp = readl(mmio + MV_RESET_CFG_OFS);
        if ((tmp & (1 << 0)) == 0) {
                hpriv->signal[idx].amps = 0x7 << 8;
                hpriv->signal[idx].pre = 0x1 << 5;
@@ -2137,7 +2482,7 @@ static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
 
 static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
 {
-       writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
+       writel(0x00000060, mmio + MV_GPIO_PORT_CTL_OFS);
 }
 
 static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
@@ -2235,11 +2580,6 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
 {
        void __iomem *port_mmio = mv_port_base(mmio, port);
 
-       /*
-        * The datasheet warns against setting ATA_RST when EDMA is active
-        * (but doesn't say what the problem might be).  So we first try
-        * to disable the EDMA engine before doing the ATA_RST operation.
-        */
        mv_reset_channel(hpriv, mmio, port);
 
        ZERO(0x028);            /* command */
@@ -2254,7 +2594,7 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
        ZERO(0x024);            /* respq outp */
        ZERO(0x020);            /* respq inp */
        ZERO(0x02c);            /* test control */
-       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
+       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT_OFS);
 }
 
 #undef ZERO
@@ -2297,38 +2637,39 @@ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
        return;
 }
 
-static void mv_setup_ifctl(void __iomem *port_mmio, int want_gen2i)
+static void mv_setup_ifcfg(void __iomem *port_mmio, int want_gen2i)
 {
-       u32 ifctl = readl(port_mmio + SATA_INTERFACE_CFG);
+       u32 ifcfg = readl(port_mmio + SATA_INTERFACE_CFG_OFS);
 
-       ifctl = (ifctl & 0xf7f) | 0x9b1000;     /* from chip spec */
+       ifcfg = (ifcfg & 0xf7f) | 0x9b1000;     /* from chip spec */
        if (want_gen2i)
-               ifctl |= (1 << 7);              /* enable gen2i speed */
-       writelfl(ifctl, port_mmio + SATA_INTERFACE_CFG);
+               ifcfg |= (1 << 7);              /* enable gen2i speed */
+       writelfl(ifcfg, port_mmio + SATA_INTERFACE_CFG_OFS);
 }
 
-/*
- * Caller must ensure that EDMA is not active,
- * by first doing mv_stop_edma() where needed.
- */
 static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
                             unsigned int port_no)
 {
        void __iomem *port_mmio = mv_port_base(mmio, port_no);
 
+       /*
+        * The datasheet warns against setting EDMA_RESET when EDMA is active
+        * (but doesn't say what the problem might be).  So we first try
+        * to disable the EDMA engine before doing the EDMA_RESET operation.
+        */
        mv_stop_edma_engine(port_mmio);
-       writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+       writelfl(EDMA_RESET, port_mmio + EDMA_CMD_OFS);
 
        if (!IS_GEN_I(hpriv)) {
-               /* Enable 3.0gb/s link speed */
-               mv_setup_ifctl(port_mmio, 1);
+               /* Enable 3.0gb/s link speed: this survives EDMA_RESET */
+               mv_setup_ifcfg(port_mmio, 1);
        }
        /*
-        * Strobing ATA_RST here causes a hard reset of the SATA transport,
+        * Strobing EDMA_RESET here causes a hard reset of the SATA transport,
         * link, and physical layers.  It resets all SATA interface registers
         * (except for SATA_INTERFACE_CFG), and issues a COMRESET to the dev.
         */
-       writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+       writelfl(EDMA_RESET, port_mmio + EDMA_CMD_OFS);
        udelay(25);     /* allow reset propagation */
        writelfl(0, port_mmio + EDMA_CMD_OFS);
 
@@ -2392,7 +2733,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
                sata_scr_read(link, SCR_STATUS, &sstatus);
                if (!IS_GEN_I(hpriv) && ++attempts >= 5 && sstatus == 0x121) {
                        /* Force 1.5gb/s link speed and try again */
-                       mv_setup_ifctl(mv_ap_base(ap), 0);
+                       mv_setup_ifcfg(mv_ap_base(ap), 0);
                        if (time_after(jiffies + HZ, deadline))
                                extra = HZ; /* only extend it once, max */
                }
@@ -2493,6 +2834,34 @@ static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
                readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
 }
 
+static unsigned int mv_in_pcix_mode(struct ata_host *host)
+{
+       struct mv_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = hpriv->base;
+       u32 reg;
+
+       if (!HAS_PCI(host) || !IS_PCIE(hpriv))
+               return 0;       /* not PCI-X capable */
+       reg = readl(mmio + MV_PCI_MODE_OFS);
+       if ((reg & MV_PCI_MODE_MASK) == 0)
+               return 0;       /* conventional PCI mode */
+       return 1;       /* chip is in PCI-X mode */
+}
+
+static int mv_pci_cut_through_okay(struct ata_host *host)
+{
+       struct mv_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = hpriv->base;
+       u32 reg;
+
+       if (!mv_in_pcix_mode(host)) {
+               reg = readl(mmio + PCI_COMMAND_OFS);
+               if (reg & PCI_COMMAND_MRDTRIG)
+                       return 0; /* not okay */
+       }
+       return 1; /* okay */
+}
+
 static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
@@ -2560,7 +2929,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
                break;
 
        case chip_7042:
-               hp_flags |= MV_HP_PCIE;
+               hp_flags |= MV_HP_PCIE | MV_HP_CUT_THROUGH;
                if (pdev->vendor == PCI_VENDOR_ID_TTI &&
                    (pdev->device == 0x2300 || pdev->device == 0x2310))
                {
@@ -2590,9 +2959,12 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
                                " and avoid the final two gigabytes on"
                                " all RocketRAID BIOS initialized drives.\n");
                }
+               /* drop through */
        case chip_6042:
                hpriv->ops = &mv6xxx_ops;
                hp_flags |= MV_HP_GEN_IIE;
+               if (board_idx == chip_6042 && mv_pci_cut_through_okay(host))
+                       hp_flags |= MV_HP_CUT_THROUGH;
 
                switch (pdev->revision) {
                case 0x0:
index 4fbb56bcb1eefbd60b5a189963e1e742ef794865..358bb0be3c0838b9233bae7b1eab1cc2b05ef1e6 100644 (file)
@@ -175,8 +175,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
        }
 
        /* Check whether this driver has already been added to a class. */
-       if ((drv->entry.next != drv->entry.prev) ||
-           (drv->entry.next != NULL)) {
+       if (drv->entry.next && !list_empty(&drv->entry)) {
                printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
                        " been registered to a class, something is wrong, but "
                        "will forge on!\n", cls->name, drv);
index 8fc429cf82b6b41d9ddf91d41a339831ac96a778..41f818be2f7ec8c4c737acaa16ecfeddc94f42b4 100644 (file)
@@ -755,11 +755,13 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector
 {
        unsigned long n_sect = bio->bi_size >> 9;
        const int rw = bio_data_dir(bio);
+       struct hd_struct *part;
 
-       all_stat_inc(disk, ios[rw], sector);
-       all_stat_add(disk, ticks[rw], duration, sector);
-       all_stat_add(disk, sectors[rw], n_sect, sector);
-       all_stat_add(disk, io_ticks, duration, sector);
+       part = get_part(disk, sector);
+       all_stat_inc(disk, part, ios[rw], sector);
+       all_stat_add(disk, part, ticks[rw], duration, sector);
+       all_stat_add(disk, part, sectors[rw], n_sect, sector);
+       all_stat_add(disk, part, io_ticks, duration, sector);
 }
 
 void
index f39f6fd8935064f01af2b91115e70111ddaa6769..b1a7a8cb65ea0252f0cbc0c5194dbc9ad9c8dcd9 100644 (file)
@@ -970,7 +970,8 @@ static int sx_set_real_termios(void *ptr)
                sx_write_channel_byte(port, hi_mask, 0x1f);
                break;
        default:
-               printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
+               printk(KERN_INFO "sx: Invalid wordsize: %u\n",
+                       (unsigned int)CFLAG & CSIZE);
                break;
        }
 
@@ -997,7 +998,8 @@ static int sx_set_real_termios(void *ptr)
                set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
        }
        sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-                       port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty));
+                       (unsigned int)port->gs.tty->termios->c_iflag,
+                       I_OTHER(port->gs.tty));
 
 /* Tell line discipline whether we will do output cooking.
  * If OPOST is set and no other output flags are set then we can do output
@@ -1010,7 +1012,8 @@ static int sx_set_real_termios(void *ptr)
                clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
        }
        sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-                       port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty));
+                       (unsigned int)port->gs.tty->termios->c_oflag,
+                       O_OTHER(port->gs.tty));
        /* port->c_dcd = sx_get_CD (port); */
        func_exit();
        return 0;
index e458b08139afb6fd638b125334ca1b602eb8e136..fa1ffbf2c621a88aa231f1262a57bd470df97e9e 100644 (file)
@@ -2742,6 +2742,10 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                                tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
                                tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
                        }
+                       if (vc->vc_utf)
+                               tty->termios->c_iflag |= IUTF8;
+                       else
+                               tty->termios->c_iflag &= ~IUTF8;
                        release_console_sem();
                        vcs_make_sysfs(tty);
                        return ret;
@@ -2918,6 +2922,8 @@ int __init vty_init(void)
        console_driver->minor_start = 1;
        console_driver->type = TTY_DRIVER_TYPE_CONSOLE;
        console_driver->init_termios = tty_std_termios;
+       if (default_utf8)
+               console_driver->init_termios.c_iflag |= IUTF8;
        console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
        tty_set_operations(console_driver, &con_ops);
        if (tty_register_driver(console_driver))
index 5938fa9629221145e6b4249d4996ca6c67e08516..faf3d89129799bc8157fa891c0176d985528c189 100644 (file)
@@ -886,7 +886,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
         */
        raid10_find_phys(conf, r10_bio);
  retry_write:
-       blocked_rdev = 0;
+       blocked_rdev = NULL;
        rcu_read_lock();
        for (i = 0;  i < conf->copies; i++) {
                int d = r10_bio->devs[i].devnum;
index 8f5ed9b4bf8327df434285194730f888d2a83a8b..3f55d47bc4b962706a7595803124796195b9c2da 100644 (file)
@@ -613,7 +613,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
        }
 
        cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-       if (cx == 0) {
+       if (!cx) {
                spin_unlock(&cx18_cards_lock);
                return -ENOMEM;
        }
index a0baf2d0ba7f307bade2c320716ce08b9b143d18..48e1a01718ec37390f72fa8ed731bfaa0d16bc78 100644 (file)
@@ -1634,7 +1634,7 @@ static int saa7134_s_fmt_overlay(struct file *file, void *priv,
        struct saa7134_fh *fh = priv;
        struct saa7134_dev *dev = fh->dev;
        int err;
-       unsigned int flags;
+       unsigned long flags;
 
        if (saa7134_no_overlay > 0) {
                printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
index a873d2b315ca33e21cfc1c3ced4e3c48f6cce273..a7714da7c283c84d48082b34540fbb05f86f85d2 100644 (file)
@@ -100,7 +100,9 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
+#ifdef CONFIG_PNP
 static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id);
+#endif
 
 /* These are the known NSC chips */
 static nsc_chip_t chips[] = {
@@ -156,9 +158,11 @@ static const struct pnp_device_id nsc_ircc_pnp_table[] = {
 MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table);
 
 static struct pnp_driver nsc_ircc_pnp_driver = {
+#ifdef CONFIG_PNP
        .name = "nsc-ircc",
        .id_table = nsc_ircc_pnp_table,
        .probe = nsc_ircc_pnp_probe,
+#endif
 };
 
 /* Some prototypes */
@@ -916,6 +920,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info)
        return 0;
 }
 
+#ifdef CONFIG_PNP
 /* PNP probing */
 static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id)
 {
@@ -952,6 +957,7 @@ static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *i
 
        return 0;
 }
+#endif
 
 /*
  * Function nsc_ircc_setup (info)
index 1f26da761e9f0067ca49450f31d48cad23cf6317..cfe0194fef71c1ab0ea9226a4f1337e567b5d7ca 100644 (file)
@@ -376,6 +376,7 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
 
 static int pnp_driver_registered;
 
+#ifdef CONFIG_PNP
 static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
                                      const struct pnp_device_id *dev_id)
 {
@@ -402,7 +403,9 @@ static struct pnp_driver smsc_ircc_pnp_driver = {
        .id_table       = smsc_ircc_pnp_table,
        .probe          = smsc_ircc_pnp_probe,
 };
-
+#else /* CONFIG_PNP */
+static struct pnp_driver smsc_ircc_pnp_driver;
+#endif
 
 /*******************************************************************************
  *
index 4009c4ce96b4fd609425e8fe3b95d30f38d705a7..57cfd72ffdf7adaf7885efd1118c45ee09d7967a 100644 (file)
@@ -1,6 +1,6 @@
 /* niu.c: Neptune ethernet driver.
  *
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -33,8 +33,8 @@
 
 #define DRV_MODULE_NAME                "niu"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.8"
-#define DRV_MODULE_RELDATE     "April 24, 2008"
+#define DRV_MODULE_VERSION     "0.9"
+#define DRV_MODULE_RELDATE     "May 4, 2008"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -7264,8 +7264,11 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
                                parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
                                        ESPC_NUM_PORTS_MACS_VAL;
 
+                               /* All of the current probing methods fail on
+                                * Maramba on-board parts.
+                                */
                                if (!parent->num_ports)
-                                       return -ENODEV;
+                                       parent->num_ports = 4;
                        }
                }
        }
index 6f245cfb662419f3f173a65073d873f4195768db..dc6f097062df3cb385d296cabfde169f54081bf4 100644 (file)
@@ -1380,6 +1380,10 @@ static const struct usb_device_id        products [] = {
        // Buffalo LUA-U2-KTX
        USB_DEVICE (0x0411, 0x003d),
        .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Buffalo LUA-U2-GT 10/100/1000
+       USB_DEVICE (0x0411, 0x006e),
+       .driver_info =  (unsigned long) &ax88178_info,
 }, {
        // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
        USB_DEVICE (0x6189, 0x182d),
index b5860b97a93e4b5d5dc8f290707f4dab7eec23f4..24fd613466b7ea0925d5c98c5aada6a82a1fc6cc 100644 (file)
@@ -459,6 +459,7 @@ static void __exit lapbeth_cleanup_driver(void)
        list_for_each_safe(entry, tmp, &lapbeth_devices) {
                lapbeth = list_entry(entry, struct lapbethdev, node);
 
+               dev_put(lapbeth->ethdev);
                unregister_netdevice(lapbeth->axdev);
        }
        rtnl_unlock();
index d5b7a76fcaad62b3d684ad9bf697b4f27d9b3c59..62fb89d8231821637de3feb9f46862aa5b1da410 100644 (file)
@@ -1,6 +1,5 @@
 config IWLWIFI
-       bool
-       default n
+       tristate
 
 config IWLCORE
        tristate "Intel Wireless Wifi Core"
index a83a40b3ebaaf9ad67b08c97a52a481645a0f4fa..0f0d27d1c4ca366916b7958798ac44570681f679 100644 (file)
@@ -184,7 +184,7 @@ ds1511_wdog_disable(void)
 static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
 {
        u8 mon, day, dow, hrs, min, sec, yrs, cen;
-       unsigned int flags;
+       unsigned long flags;
 
        /*
         * won't have to change this for a while
@@ -247,7 +247,7 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
 static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
 {
        unsigned int century;
-       unsigned int flags;
+       unsigned long flags;
 
        spin_lock_irqsave(&ds1511_lock, flags);
        rtc_disable_update();
index c1f2adefad410287fe170ae77a8baa47a8611187..5043150019ac0788e91d4a42ee1d49955c99d527 100644 (file)
@@ -965,8 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
  * Insert character into the screen at the current position with the
  * current color and highlight. This function does NOT do cursor movement.
  */
-static int
-tty3270_put_character(struct tty3270 *tp, char ch)
+static void tty3270_put_character(struct tty3270 *tp, char ch)
 {
        struct tty3270_line *line;
        struct tty3270_cell *cell;
@@ -986,7 +985,6 @@ tty3270_put_character(struct tty3270 *tp, char ch)
        cell->character = tp->view.ascebc[(unsigned int) ch];
        cell->highlight = tp->highlight;
        cell->f_color = tp->f_color;
-       return 1;
 }
 
 /*
@@ -1612,16 +1610,15 @@ tty3270_write(struct tty_struct * tty,
 /*
  * Put single characters to the ttys character buffer
  */
-static void
-tty3270_put_char(struct tty_struct *tty, unsigned char ch)
+static int tty3270_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct tty3270 *tp;
 
        tp = tty->driver_data;
-       if (!tp)
-               return;
-       if (tp->char_count < TTY3270_CHAR_BUF_SIZE)
-               tp->char_buf[tp->char_count++] = ch;
+       if (!tp || tp->char_count >= TTY3270_CHAR_BUF_SIZE)
+               return 0;
+       tp->char_buf[tp->char_count++] = ch;
+       return 1;
 }
 
 /*
index 40ef948fcb3a5e9b2441bacb6a78fd65f9a693cf..9c21b8f43f9b70ab8b559d9a880bfb160d73ec01 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/cio.h>
 #include <asm/uaccess.h>
+#include <asm/cio.h>
 
 #include "blacklist.h"
 #include "cio.h"
@@ -43,164 +44,169 @@ typedef enum {add, free} range_action;
  * Function: blacklist_range
  * (Un-)blacklist the devices from-to
  */
-static void
-blacklist_range (range_action action, unsigned int from, unsigned int to,
-                unsigned int ssid)
+static int blacklist_range(range_action action, unsigned int from_ssid,
+                          unsigned int to_ssid, unsigned int from,
+                          unsigned int to, int msgtrigger)
 {
-       if (!to)
-               to = from;
-
-       if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
-               printk (KERN_WARNING "cio: Invalid blacklist range "
-                       "0.%x.%04x to 0.%x.%04x, skipping\n",
-                       ssid, from, ssid, to);
-               return;
+       if ((from_ssid > to_ssid) || ((from_ssid == to_ssid) && (from > to))) {
+               if (msgtrigger)
+                       printk(KERN_WARNING "cio: Invalid cio_ignore range "
+                              "0.%x.%04x-0.%x.%04x\n", from_ssid, from,
+                              to_ssid, to);
+               return 1;
        }
-       for (; from <= to; from++) {
+
+       while ((from_ssid < to_ssid) || ((from_ssid == to_ssid) &&
+              (from <= to))) {
                if (action == add)
-                       set_bit (from, bl_dev[ssid]);
+                       set_bit(from, bl_dev[from_ssid]);
                else
-                       clear_bit (from, bl_dev[ssid]);
+                       clear_bit(from, bl_dev[from_ssid]);
+               from++;
+               if (from > __MAX_SUBCHANNEL) {
+                       from_ssid++;
+                       from = 0;
+               }
        }
+
+       return 0;
 }
 
-/*
- * Function: blacklist_busid
- * Get devno/busid from given string.
- * Shamelessly grabbed from dasd_devmap.c.
- */
-static int
-blacklist_busid(char **str, int *id0, int *ssid, int *devno)
+static int pure_hex(char **cp, unsigned int *val, int min_digit,
+                   int max_digit, int max_val)
 {
-       int val, old_style;
-       char *sav;
+       int diff;
+       unsigned int value;
 
-       sav = *str;
+       diff = 0;
+       *val = 0;
 
-       /* check for leading '0x' */
-       old_style = 0;
-       if ((*str)[0] == '0' && (*str)[1] == 'x') {
-               *str += 2;
-               old_style = 1;
-       }
-       if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
-               goto confused;
-       val = simple_strtoul(*str, str, 16);
-       if (old_style || (*str)[0] != '.') {
-               *id0 = *ssid = 0;
-               if (val < 0 || val > 0xffff)
-                       goto confused;
-               *devno = val;
-               if ((*str)[0] != ',' && (*str)[0] != '-' &&
-                   (*str)[0] != '\n' && (*str)[0] != '\0')
-                       goto confused;
-               return 0;
+       while (isxdigit(**cp) && (diff <= max_digit)) {
+
+               if (isdigit(**cp))
+                       value = **cp - '0';
+               else
+                       value = tolower(**cp) - 'a' + 10;
+               *val = *val * 16 + value;
+               (*cp)++;
+               diff++;
        }
-       /* New style x.y.z busid */
-       if (val < 0 || val > 0xff)
-               goto confused;
-       *id0 = val;
-       (*str)++;
-       if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
-               goto confused;
-       val = simple_strtoul(*str, str, 16);
-       if (val < 0 || val > 0xff || (*str)++[0] != '.')
-               goto confused;
-       *ssid = val;
-       if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
-               goto confused;
-       val = simple_strtoul(*str, str, 16);
-       if (val < 0 || val > 0xffff)
-               goto confused;
-       *devno = val;
-       if ((*str)[0] != ',' && (*str)[0] != '-' &&
-           (*str)[0] != '\n' && (*str)[0] != '\0')
-               goto confused;
+
+       if ((diff < min_digit) || (diff > max_digit) || (*val > max_val))
+               return 1;
+
        return 0;
-confused:
-       strsep(str, ",\n");
-       printk(KERN_WARNING "cio: Invalid cio_ignore parameter '%s'\n", sav);
-       return 1;
 }
 
-static int
-blacklist_parse_parameters (char *str, range_action action)
+static int parse_busid(char *str, int *cssid, int *ssid, int *devno,
+                      int msgtrigger)
 {
-       int from, to, from_id0, to_id0, from_ssid, to_ssid;
-
-       while (*str != 0 && *str != '\n') {
-               range_action ra = action;
-               while(*str == ',')
-                       str++;
-               if (*str == '!') {
-                       ra = !action;
-                       ++str;
+       char *str_work;
+       int val, rc, ret;
+
+       rc = 1;
+
+       if (*str == '\0')
+               goto out;
+
+       /* old style */
+       str_work = str;
+       val = simple_strtoul(str, &str_work, 16);
+
+       if (*str_work == '\0') {
+               if (val <= __MAX_SUBCHANNEL) {
+                       *devno = val;
+                       *ssid = 0;
+                       *cssid = 0;
+                       rc = 0;
                }
+               goto out;
+       }
 
-               /*
-                * Since we have to parse the proc commands and the
-                * kernel arguments we have to check four cases
-                */
-               if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
-                   strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
-                       int j;
-
-                       str += 3;
-                       for (j=0; j <= __MAX_SSID; j++)
-                               blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
-               } else {
-                       int rc;
+       /* new style */
+       str_work = str;
+       ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID);
+       if (ret || (str_work[0] != '.'))
+               goto out;
+       str_work++;
+       ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID);
+       if (ret || (str_work[0] != '.'))
+               goto out;
+       str_work++;
+       ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL);
+       if (ret || (str_work[0] != '\0'))
+               goto out;
+
+       rc = 0;
+out:
+       if (rc && msgtrigger)
+               printk(KERN_WARNING "cio: Invalid cio_ignore device '%s'\n",
+                      str);
+
+       return rc;
+}
 
-                       rc = blacklist_busid(&str, &from_id0,
-                                            &from_ssid, &from);
-                       if (rc)
-                               continue;
-                       to = from;
-                       to_id0 = from_id0;
-                       to_ssid = from_ssid;
-                       if (*str == '-') {
-                               str++;
-                               rc = blacklist_busid(&str, &to_id0,
-                                                    &to_ssid, &to);
-                               if (rc)
-                                       continue;
-                       }
-                       if (*str == '-') {
-                               printk(KERN_WARNING "cio: invalid cio_ignore "
-                                       "parameter '%s'\n",
-                                       strsep(&str, ",\n"));
-                               continue;
-                       }
-                       if ((from_id0 != to_id0) ||
-                           (from_ssid != to_ssid)) {
-                               printk(KERN_WARNING "cio: invalid cio_ignore "
-                                      "range %x.%x.%04x-%x.%x.%04x\n",
-                                      from_id0, from_ssid, from,
-                                      to_id0, to_ssid, to);
-                               continue;
+static int blacklist_parse_parameters(char *str, range_action action,
+                                     int msgtrigger)
+{
+       int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
+       int rc, totalrc;
+       char *parm;
+       range_action ra;
+
+       totalrc = 0;
+
+       while ((parm = strsep(&str, ","))) {
+               rc = 0;
+               ra = action;
+               if (*parm == '!') {
+                       if (ra == add)
+                               ra = free;
+                       else
+                               ra = add;
+                       parm++;
+               }
+               if (strcmp(parm, "all") == 0) {
+                       from_cssid = 0;
+                       from_ssid = 0;
+                       from = 0;
+                       to_cssid = __MAX_CSSID;
+                       to_ssid = __MAX_SSID;
+                       to = __MAX_SUBCHANNEL;
+               } else {
+                       rc = parse_busid(strsep(&parm, "-"), &from_cssid,
+                                        &from_ssid, &from, msgtrigger);
+                       if (!rc) {
+                               if (parm != NULL)
+                                       rc = parse_busid(parm, &to_cssid,
+                                                        &to_ssid, &to,
+                                                        msgtrigger);
+                               else {
+                                       to_cssid = from_cssid;
+                                       to_ssid = from_ssid;
+                                       to = from;
+                               }
                        }
-                       blacklist_range (ra, from, to, to_ssid);
                }
+               if (!rc) {
+                       rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
+                                            msgtrigger);
+                       if (rc)
+                               totalrc = 1;
+               } else
+                       totalrc = 1;
        }
-       return 1;
+
+       return totalrc;
 }
 
-/* Parsing the commandline for blacklist parameters, e.g. to blacklist
- * bus ids 0.0.1234, 0.0.1235 and 0.0.1236, you could use any of:
- * - cio_ignore=1234-1236
- * - cio_ignore=0x1234-0x1235,1236
- * - cio_ignore=0x1234,1235-1236
- * - cio_ignore=1236 cio_ignore=1234-0x1236
- * - cio_ignore=1234 cio_ignore=1236 cio_ignore=0x1235
- * - cio_ignore=0.0.1234-0.0.1236
- * - cio_ignore=0.0.1234,0x1235,1236
- * - ...
- */
 static int __init
 blacklist_setup (char *str)
 {
        CIO_MSG_EVENT(6, "Reading blacklist parameters\n");
-       return blacklist_parse_parameters (str, add);
+       if (blacklist_parse_parameters(str, add, 1))
+               return 0;
+       return 1;
 }
 
 __setup ("cio_ignore=", blacklist_setup);
@@ -224,27 +230,23 @@ is_blacklisted (int ssid, int devno)
  * Function: blacklist_parse_proc_parameters
  * parse the stuff which is piped to /proc/cio_ignore
  */
-static void
-blacklist_parse_proc_parameters (char *buf)
+static int blacklist_parse_proc_parameters(char *buf)
 {
-       if (strncmp (buf, "free ", 5) == 0) {
-               blacklist_parse_parameters (buf + 5, free);
-       } else if (strncmp (buf, "add ", 4) == 0) {
-               /* 
-                * We don't need to check for known devices since
-                * css_probe_device will handle this correctly. 
-                */
-               blacklist_parse_parameters (buf + 4, add);
-       } else {
-               printk (KERN_WARNING "cio: cio_ignore: Parse error; \n"
-                       KERN_WARNING "try using 'free all|<devno-range>,"
-                                    "<devno-range>,...'\n"
-                       KERN_WARNING "or 'add <devno-range>,"
-                                    "<devno-range>,...'\n");
-               return;
-       }
+       int rc;
+       char *parm;
+
+       parm = strsep(&buf, " ");
+
+       if (strcmp("free", parm) == 0)
+               rc = blacklist_parse_parameters(buf, free, 0);
+       else if (strcmp("add", parm) == 0)
+               rc = blacklist_parse_parameters(buf, add, 0);
+       else
+               return 1;
 
        css_schedule_reprobe();
+
+       return rc;
 }
 
 /* Iterator struct for all devices. */
@@ -328,6 +330,8 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
                 size_t user_len, loff_t *offset)
 {
        char *buf;
+       size_t i;
+       ssize_t rc, ret;
 
        if (*offset)
                return -EINVAL;
@@ -336,16 +340,27 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
        buf = vmalloc (user_len + 1); /* maybe better use the stack? */
        if (buf == NULL)
                return -ENOMEM;
+       memset(buf, 0, user_len + 1);
+
        if (strncpy_from_user (buf, user_buf, user_len) < 0) {
-               vfree (buf);
-               return -EFAULT;
+               rc = -EFAULT;
+               goto out_free;
        }
-       buf[user_len] = '\0';
 
-       blacklist_parse_proc_parameters (buf);
+       i = user_len - 1;
+       while ((i >= 0) && (isspace(buf[i]) || (buf[i] == 0))) {
+               buf[i] = '\0';
+               i--;
+       }
+       ret = blacklist_parse_proc_parameters(buf);
+       if (ret)
+               rc = -EINVAL;
+       else
+               rc = user_len;
 
+out_free:
        vfree (buf);
-       return user_len;
+       return rc;
 }
 
 static const struct seq_operations cio_ignore_proc_seq_ops = {
index 08a578161306e1088f4fe6786ea85b518cfd7a12..82c6a2d451284424c40fc14791736f642ef80934 100644 (file)
@@ -39,23 +39,6 @@ debug_info_t *cio_debug_msg_id;
 debug_info_t *cio_debug_trace_id;
 debug_info_t *cio_debug_crw_id;
 
-int cio_show_msg;
-
-static int __init
-cio_setup (char *parm)
-{
-       if (!strcmp (parm, "yes"))
-               cio_show_msg = 1;
-       else if (!strcmp (parm, "no"))
-               cio_show_msg = 0;
-       else
-               printk(KERN_ERR "cio: cio_setup: "
-                      "invalid cio_msg parameter '%s'", parm);
-       return 1;
-}
-
-__setup ("cio_msg=", cio_setup);
-
 /*
  * Function: cio_debug_init
  * Initializes three debug logs for common I/O:
@@ -166,7 +149,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
 
        stsch (sch->schid, &sch->schib);
 
-       CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
+       CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
                      "subchannel 0.%x.%04x!\n", sch->schid.ssid,
                      sch->schid.sch_no);
        sprintf(dbf_text, "no%s", sch->dev.bus_id);
@@ -567,10 +550,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
         * ... just being curious we check for non I/O subchannels
         */
        if (sch->st != 0) {
-               CIO_DEBUG(KERN_INFO, 0,
-                         "Subchannel 0.%x.%04x reports "
-                         "non-I/O subchannel type %04X\n",
-                         sch->schid.ssid, sch->schid.sch_no, sch->st);
+               CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports "
+                             "non-I/O subchannel type %04X\n",
+                             sch->schid.ssid, sch->schid.sch_no, sch->st);
                /* We stop here for non-io subchannels. */
                err = sch->st;
                goto out;
@@ -588,7 +570,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
                 * This device must not be known to Linux. So we simply
                 * say that there is no device and return ENODEV.
                 */
-               CIO_MSG_EVENT(4, "Blacklisted device detected "
+               CIO_MSG_EVENT(6, "Blacklisted device detected "
                              "at devno %04X, subchannel set %x\n",
                              sch->schib.pmcw.dev, sch->schid.ssid);
                err = -ENODEV;
@@ -601,12 +583,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        sch->lpm = sch->schib.pmcw.pam & sch->opm;
        sch->isc = 3;
 
-       CIO_DEBUG(KERN_INFO, 0,
-                 "Detected device %04x on subchannel 0.%x.%04X"
-                 " - PIM = %02X, PAM = %02X, POM = %02X\n",
-                 sch->schib.pmcw.dev, sch->schid.ssid,
-                 sch->schid.sch_no, sch->schib.pmcw.pim,
-                 sch->schib.pmcw.pam, sch->schib.pmcw.pom);
+       CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X "
+                     "- PIM = %02X, PAM = %02X, POM = %02X\n",
+                     sch->schib.pmcw.dev, sch->schid.ssid,
+                     sch->schid.sch_no, sch->schib.pmcw.pim,
+                     sch->schib.pmcw.pam, sch->schib.pmcw.pom);
 
        /*
         * We now have to initially ...
index 3c75412904dc495eade9f6627b148adc730e6e82..6e933aebe01308e2882f45f0320c72a9612e133d 100644 (file)
@@ -118,6 +118,4 @@ extern void *cio_get_console_priv(void);
 #define cio_get_console_priv() NULL
 #endif
 
-extern int cio_show_msg;
-
 #endif
index d7429ef6c666c1c56a4fa8b2ab05e04cc69901cf..e64e8278c42e9979af1d35fb57c685be02327731 100644 (file)
@@ -31,10 +31,4 @@ static inline void CIO_HEX_EVENT(int level, void *data, int length)
        }
 }
 
-#define CIO_DEBUG(printk_level, event_level, msg...) do {      \
-               if (cio_show_msg)                               \
-                       printk(printk_level "cio: " msg);       \
-               CIO_MSG_EVENT(event_level, msg);                \
-       } while (0)
-
 #endif
index 595e327d2f76cc4f47d7f7682fb7e99e88647c3e..a76956512b2d41963a0bd89ddba91a69f7b2553a 100644 (file)
@@ -570,7 +570,7 @@ static void reprobe_all(struct work_struct *unused)
 {
        int ret;
 
-       CIO_MSG_EVENT(2, "reprobe start\n");
+       CIO_MSG_EVENT(4, "reprobe start\n");
 
        need_reprobe = 0;
        /* Make sure initial subchannel scan is done. */
@@ -578,7 +578,7 @@ static void reprobe_all(struct work_struct *unused)
                   atomic_read(&ccw_device_init_count) == 0);
        ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
 
-       CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
+       CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
                      need_reprobe);
 }
 
index abfd601d237a1a07c9aa852e671a8bde507f6cc4..e22813db74a2b6bb81d2d0e1e27ec64acde946e2 100644 (file)
@@ -341,7 +341,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
                rc = device_schedule_callback(&cdev->dev,
                                              ccw_device_remove_orphan_cb);
                if (rc)
-                       CIO_MSG_EVENT(2, "Couldn't unregister orphan "
+                       CIO_MSG_EVENT(0, "Couldn't unregister orphan "
                                      "0.%x.%04x\n",
                                      cdev->private->dev_id.ssid,
                                      cdev->private->dev_id.devno);
@@ -351,7 +351,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
        rc = device_schedule_callback(cdev->dev.parent,
                                      ccw_device_remove_sch_cb);
        if (rc)
-               CIO_MSG_EVENT(2, "Couldn't unregister disconnected device "
+               CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
                              "0.%x.%04x\n",
                              cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno);
@@ -397,7 +397,7 @@ int ccw_device_set_offline(struct ccw_device *cdev)
        if (ret == 0)
                wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
        else {
-               CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+               CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
                              "device 0.%x.%04x\n",
                              ret, cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno);
@@ -433,7 +433,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
        if (ret == 0)
                wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
        else {
-               CIO_MSG_EVENT(2, "ccw_device_online returned %d, "
+               CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
                              "device 0.%x.%04x\n",
                              ret, cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno);
@@ -451,7 +451,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
        if (ret == 0)
                wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
        else
-               CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+               CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
                              "device 0.%x.%04x\n",
                              ret, cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno);
@@ -803,7 +803,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch,
        other_sch = to_subchannel(get_device(cdev->dev.parent));
        ret = device_move(&cdev->dev, &sch->dev);
        if (ret) {
-               CIO_MSG_EVENT(2, "Moving disconnected device 0.%x.%04x failed "
+               CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed "
                              "(ret=%d)!\n", cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno, ret);
                put_device(&other_sch->dev);
@@ -933,7 +933,7 @@ io_subchannel_register(struct work_struct *work)
                        ret = device_reprobe(&cdev->dev);
                        if (ret)
                                /* We can't do much here. */
-                               CIO_MSG_EVENT(2, "device_reprobe() returned"
+                               CIO_MSG_EVENT(0, "device_reprobe() returned"
                                              " %d for 0.%x.%04x\n", ret,
                                              cdev->private->dev_id.ssid,
                                              cdev->private->dev_id.devno);
@@ -1086,7 +1086,7 @@ static void ccw_device_move_to_sch(struct work_struct *work)
        rc = device_move(&cdev->dev, &sch->dev);
        mutex_unlock(&sch->reg_mutex);
        if (rc) {
-               CIO_MSG_EVENT(2, "Moving device 0.%x.%04x to subchannel "
+               CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel "
                              "0.%x.%04x failed (ret=%d)!\n",
                              cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno, sch->schid.ssid,
@@ -1446,8 +1446,7 @@ ccw_device_remove (struct device *dev)
                        wait_event(cdev->private->wait_q,
                                   dev_fsm_final_state(cdev));
                else
-                       //FIXME: we can't fail!
-                       CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+                       CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
                                      "device 0.%x.%04x\n",
                                      ret, cdev->private->dev_id.ssid,
                                      cdev->private->dev_id.devno);
@@ -1524,7 +1523,7 @@ static int recovery_check(struct device *dev, void *data)
        spin_lock_irq(cdev->ccwlock);
        switch (cdev->private->state) {
        case DEV_STATE_DISCONNECTED:
-               CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n",
+               CIO_MSG_EVENT(4, "recovery: trigger 0.%x.%04x\n",
                              cdev->private->dev_id.ssid,
                              cdev->private->dev_id.devno);
                dev_fsm_event(cdev, DEV_EVENT_VERIFY);
@@ -1554,7 +1553,7 @@ static void recovery_work_func(struct work_struct *unused)
                }
                spin_unlock_irq(&recovery_lock);
        } else
-               CIO_MSG_EVENT(2, "recovery: end\n");
+               CIO_MSG_EVENT(4, "recovery: end\n");
 }
 
 static DECLARE_WORK(recovery_work, recovery_work_func);
@@ -1572,7 +1571,7 @@ void ccw_device_schedule_recovery(void)
 {
        unsigned long flags;
 
-       CIO_MSG_EVENT(2, "recovery: schedule\n");
+       CIO_MSG_EVENT(4, "recovery: schedule\n");
        spin_lock_irqsave(&recovery_lock, flags);
        if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
                recovery_phase = 0;
index 99403b0a97a7737a4865f72d41453048d1fb2600..e268d5a77c12633c4d80d5493add727229fe94fa 100644 (file)
@@ -322,10 +322,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
        same_dev = 0; /* Keep the compiler quiet... */
        switch (state) {
        case DEV_STATE_NOT_OPER:
-               CIO_DEBUG(KERN_WARNING, 2,
-                         "SenseID : unknown device %04x on subchannel "
-                         "0.%x.%04x\n", cdev->private->dev_id.devno,
-                         sch->schid.ssid, sch->schid.sch_no);
+               CIO_MSG_EVENT(2, "SenseID : unknown device %04x on "
+                             "subchannel 0.%x.%04x\n",
+                             cdev->private->dev_id.devno,
+                             sch->schid.ssid, sch->schid.sch_no);
                break;
        case DEV_STATE_OFFLINE:
                if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -348,20 +348,19 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                        return;
                }
                /* Issue device info message. */
-               CIO_DEBUG(KERN_INFO, 2,
-                         "SenseID : device 0.%x.%04x reports: "
-                         "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
-                         "%04X/%02X\n",
-                         cdev->private->dev_id.ssid,
-                         cdev->private->dev_id.devno,
-                         cdev->id.cu_type, cdev->id.cu_model,
-                         cdev->id.dev_type, cdev->id.dev_model);
+               CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
+                             "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
+                             "%04X/%02X\n",
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno,
+                             cdev->id.cu_type, cdev->id.cu_model,
+                             cdev->id.dev_type, cdev->id.dev_model);
                break;
        case DEV_STATE_BOXED:
-               CIO_DEBUG(KERN_WARNING, 2,
-                         "SenseID : boxed device %04x on subchannel "
-                         "0.%x.%04x\n", cdev->private->dev_id.devno,
-                         sch->schid.ssid, sch->schid.sch_no);
+               CIO_MSG_EVENT(0, "SenseID : boxed device %04x on "
+                             " subchannel 0.%x.%04x\n",
+                             cdev->private->dev_id.devno,
+                             sch->schid.ssid, sch->schid.sch_no);
                break;
        }
        cdev->private->state = state;
@@ -443,9 +442,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
 
 
        if (state == DEV_STATE_BOXED)
-               CIO_DEBUG(KERN_WARNING, 2,
-                         "Boxed device %04x on subchannel %04x\n",
-                         cdev->private->dev_id.devno, sch->schid.sch_no);
+               CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
+                             cdev->private->dev_id.devno, sch->schid.sch_no);
 
        if (cdev->private->flags.donotify) {
                cdev->private->flags.donotify = 0;
@@ -900,7 +898,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
                        /* Basic sense hasn't started. Try again. */
                        ccw_device_do_sense(cdev, irb);
                else {
-                       CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited "
+                       CIO_MSG_EVENT(0, "0.%x.%04x: unsolicited "
                                      "interrupt during w4sense...\n",
                                      cdev->private->dev_id.ssid,
                                      cdev->private->dev_id.devno);
@@ -1169,8 +1167,10 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
 static void
 ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
 {
-       CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n",
-                     cdev->private->state, dev_event);
+       CIO_MSG_EVENT(0, "Internal state [%i][%i] not handled for device "
+                     "0.%x.%04x\n", cdev->private->state, dev_event,
+                     cdev->private->dev_id.ssid,
+                     cdev->private->dev_id.devno);
        BUG();
 }
 
index dc4d87f77f6c4bbb45dd1e15fe9582c5cf3f474f..cba7020517edbaa300e5fd2cfc3b80d52380aea3 100644 (file)
@@ -214,7 +214,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
                 *     sense id information. So, for intervention required,
                 *     we use the "whack it until it talks" strategy...
                 */
-               CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
+               CIO_MSG_EVENT(0, "SenseID : device %04x on Subchannel "
                              "0.%x.%04x reports cmd reject\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no);
@@ -239,7 +239,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
 
                lpm = to_io_private(sch)->orb.lpm;
                if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
-                       CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
+                       CIO_MSG_EVENT(4, "SenseID : path %02X for device %04x "
                                      "on subchannel 0.%x.%04x is "
                                      "'not operational'\n", lpm,
                                      cdev->private->dev_id.devno,
index c52449a1f9fce93f2af14456c88cb7dc7e390d96..ba559053402e341134af40565b8a571f4b3359d9 100644 (file)
@@ -79,7 +79,7 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
                        /* ret is 0, -EBUSY, -EACCES or -ENODEV */
                        if (ret != -EACCES)
                                return ret;
-                       CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
+                       CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel "
                                      "0.%x.%04x, lpm %02X, became 'not "
                                      "operational'\n",
                                      cdev->private->dev_id.devno,
@@ -159,7 +159,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                u8 lpm;
 
                lpm = to_io_private(sch)->orb.lpm;
-               CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+               CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, lpm);
@@ -275,7 +275,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
                        return ret;
        }
        /* PGID command failed on this path. */
-       CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
+       CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel "
                      "0.%x.%04x, lpm %02X, became 'not operational'\n",
                      cdev->private->dev_id.devno, sch->schid.ssid,
                      sch->schid.sch_no, cdev->private->imask);
@@ -317,7 +317,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
                        return ret;
        }
        /* nop command failed on this path. */
-       CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
+       CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel "
                      "0.%x.%04x, lpm %02X, became 'not operational'\n",
                      cdev->private->dev_id.devno, sch->schid.ssid,
                      sch->schid.sch_no, cdev->private->imask);
@@ -362,7 +362,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
                return -EAGAIN;
        }
        if (irb->scsw.cc == 3) {
-               CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+               CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, cdev->private->imask);
@@ -391,7 +391,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
                return -ETIME;
        }
        if (irb->scsw.cc == 3) {
-               CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
+               CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
                              sch->schid.sch_no, cdev->private->imask);
index 4d4b54277c43d2554e81f4cf5207ed8e3107995b..5080f343ad7482ebac5addfc19768ac5adfeeae2 100644 (file)
@@ -48,10 +48,11 @@ s390_collect_crw_info(void *param)
        int ccode;
        struct semaphore *sem;
        unsigned int chain;
+       int ignore;
 
        sem = (struct semaphore *)param;
 repeat:
-       down_interruptible(sem);
+       ignore = down_interruptible(sem);
        chain = 0;
        while (1) {
                if (unlikely(chain > 1)) {
index 4fab0c23814c90dda8bf55b85e6242c6dbc07d96..b87037ec9805502a52cd4655f6d40a96847d3b66 100644 (file)
@@ -41,7 +41,7 @@
 #define BPP_DELAY 100
 
 static const unsigned  BPP_MAJOR = LP_MAJOR;
-static const chardev_name = "bpp";
+static const char *bpp_dev_name = "bpp";
 
 /* When switching from compatibility to a mode where I can read, try
    the following mode first. */
index 0fb5bf4c43acd4500b93bc51b1e010c17e3a70d7..8508816f303d08144fb8377da3c5c780ae7c5a9e 100644 (file)
@@ -1967,45 +1967,6 @@ cleanup:
        return rcode;
 }
 
-
-/*
- * This routine returns information about the system.  This does not effect
- * any logic and if the info is wrong - it doesn't matter.
- */
-
-/* Get all the info we can not get from kernel services */
-static int adpt_system_info(void __user *buffer)
-{
-       sysInfo_S si;
-
-       memset(&si, 0, sizeof(si));
-
-       si.osType = OS_LINUX;
-       si.osMajorVersion = 0;
-       si.osMinorVersion = 0;
-       si.osRevision = 0;
-       si.busType = SI_PCI_BUS;
-       si.processorFamily = DPTI_sig.dsProcessorFamily;
-
-#if defined __i386__ 
-       adpt_i386_info(&si);
-#elif defined (__ia64__)
-       adpt_ia64_info(&si);
-#elif defined(__sparc__)
-       adpt_sparc_info(&si);
-#elif defined (__alpha__)
-       adpt_alpha_info(&si);
-#else
-       si.processorType = 0xff ;
-#endif
-       if(copy_to_user(buffer, &si, sizeof(si))){
-               printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
 #if defined __ia64__ 
 static void adpt_ia64_info(sysInfo_S* si)
 {
@@ -2016,7 +1977,6 @@ static void adpt_ia64_info(sysInfo_S* si)
 }
 #endif
 
-
 #if defined __sparc__ 
 static void adpt_sparc_info(sysInfo_S* si)
 {
@@ -2026,7 +1986,6 @@ static void adpt_sparc_info(sysInfo_S* si)
        si->processorType = PROC_ULTRASPARC;
 }
 #endif
-
 #if defined __alpha__ 
 static void adpt_alpha_info(sysInfo_S* si)
 {
@@ -2038,7 +1997,6 @@ static void adpt_alpha_info(sysInfo_S* si)
 #endif
 
 #if defined __i386__
-
 static void adpt_i386_info(sysInfo_S* si)
 {
        // This is all the info we need for now
@@ -2059,9 +2017,45 @@ static void adpt_i386_info(sysInfo_S* si)
                break;
        }
 }
+#endif
+
+/*
+ * This routine returns information about the system.  This does not effect
+ * any logic and if the info is wrong - it doesn't matter.
+ */
 
+/* Get all the info we can not get from kernel services */
+static int adpt_system_info(void __user *buffer)
+{
+       sysInfo_S si;
+
+       memset(&si, 0, sizeof(si));
+
+       si.osType = OS_LINUX;
+       si.osMajorVersion = 0;
+       si.osMinorVersion = 0;
+       si.osRevision = 0;
+       si.busType = SI_PCI_BUS;
+       si.processorFamily = DPTI_sig.dsProcessorFamily;
+
+#if defined __i386__
+       adpt_i386_info(&si);
+#elif defined (__ia64__)
+       adpt_ia64_info(&si);
+#elif defined(__sparc__)
+       adpt_sparc_info(&si);
+#elif defined (__alpha__)
+       adpt_alpha_info(&si);
+#else
+       si.processorType = 0xff ;
 #endif
+       if (copy_to_user(buffer, &si, sizeof(si))){
+               printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
+               return -EFAULT;
+       }
 
+       return 0;
+}
 
 static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
              ulong arg)
index 924cd5a51676a9b7212016722d6d319b60817608..337746d460438417281d25c3aa9aec863f3e002d 100644 (file)
@@ -316,19 +316,6 @@ static int adpt_close(struct inode *inode, struct file *file);
 static void adpt_delay(int millisec);
 #endif
 
-#if defined __ia64__ 
-static void adpt_ia64_info(sysInfo_S* si);
-#endif
-#if defined __sparc__ 
-static void adpt_sparc_info(sysInfo_S* si);
-#endif
-#if defined __alpha__ 
-static void adpt_sparc_info(sysInfo_S* si);
-#endif
-#if defined __i386__
-static void adpt_i386_info(sysInfo_S* si);
-#endif
-
 #define PRINT_BUFFER_SIZE     512
 
 #define HBA_FLAGS_DBG_FLAGS_MASK         0xffff0000    // Mask for debug flags
index 1e2b9d826f69a5db2756e8eb477f2249587122e4..eab032733790d5524ac9f14e8596c1a5a62e462c 100644 (file)
@@ -556,7 +556,7 @@ static int uart_chars_in_buffer(struct tty_struct *tty)
 static void uart_flush_buffer(struct tty_struct *tty)
 {
        struct uart_state *state = tty->driver_data;
-       struct uart_port *port = state->port;
+       struct uart_port *port;
        unsigned long flags;
 
        /*
@@ -568,6 +568,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
                return;
        }
 
+       port = state->port;
        pr_debug("uart_flush_buffer(%d) called\n", tty->index);
 
        spin_lock_irqsave(&port->lock, flags);
index 33b467a8352dc95892b09dba5a023d64968ebc1f..1ef6df395e0c83954351fa2dcec9d260a6c97a52 100644 (file)
@@ -129,7 +129,7 @@ config USB_ISP1760_PCI
 
 config USB_ISP1760_OF
        bool "Support for the OF platform bus"
-       depends on USB_ISP1760_HCD && OF
+       depends on USB_ISP1760_HCD && PPC_OF
        ---help---
          Enables support for the device present on the PowerPC
          OpenFirmware platform bus.
index 8a217648b250311abf685cd0f89cc558de41f7ca..a01e987c7d32e274d8d060ef15276fae913a1ca0 100644 (file)
@@ -643,7 +643,7 @@ static void read_buf_callback(struct urb *urb)
 static int iuu_bulk_write(struct usb_serial_port *port)
 {
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       unsigned int flags;
+       unsigned long flags;
        int result;
        int i;
        char *buf_ptr = port->write_urb->transfer_buffer;
@@ -694,7 +694,7 @@ static void iuu_uart_read_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       unsigned int flags;
+       unsigned long flags;
        int status;
        int error = 0;
        int len = 0;
@@ -759,7 +759,7 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
                          int count)
 {
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       unsigned int flags;
+       unsigned long flags;
        dbg("%s - enter", __func__);
 
        if (count > 256)
index 275d9dab0c6108e2f56b73c6bb5d2da1d3fdedc2..79f85dc402d650c9755de43b4c98ec1e18987ec0 100644 (file)
@@ -329,7 +329,7 @@ static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *
        if (!info->screen_base)
                goto out_unmap_regs;
 
-       bw2_blank(0, info);
+       bw2_blank(FB_BLANK_UNBLANK, info);
 
        bw2_init_fix(info, linebytes);
 
index 010ea53978f822cdc7cafd9dce2f85c7ec9054b5..e31e26a6bb79a449fc15f600f3642f4bb016b397 100644 (file)
@@ -398,7 +398,7 @@ static int __devinit cg3_probe(struct of_device *op,
        if (!info->screen_base)
                goto out_unmap_regs;
 
-       cg3_blank(0, info);
+       cg3_blank(FB_BLANK_UNBLANK, info);
 
        if (!of_find_property(dp, "width", NULL)) {
                err = cg3_do_default_mode(par);
index fc90db6da65a94267e8e2e8f22865b5843abdabb..8000bccecdc6af3617f5ca1c8693486acd60e134 100644 (file)
@@ -767,7 +767,7 @@ static int __devinit cg6_probe(struct of_device *op,
 
        cg6_bt_init(par);
        cg6_chip_init(info);
-       cg6_blank(0, info);
+       cg6_blank(FB_BLANK_UNBLANK, info);
 
        if (fb_alloc_cmap(&info->cmap, 256, 0))
                goto out_unmap_regs;
index 93dca3e2aa502d7537aca3fbae7069af80b4f6eb..0f42a696d1766ea84c997dc584128b46b727dca1 100644 (file)
@@ -987,7 +987,7 @@ static int __devinit ffb_probe(struct of_device *op,
         * chosen console, it will have video outputs off in
         * the DAC.
         */
-       ffb_blank(0, info);
+       ffb_blank(FB_BLANK_UNBLANK, info);
 
        if (fb_alloc_cmap(&info->cmap, 256, 0))
                goto out_unmap_dac;
index f3160fc29795354a680e13d5a576876f70b42af7..fb129928d5d5fadb1f0997f664f5b213dc053d76 100644 (file)
@@ -601,7 +601,7 @@ static int __devinit leo_probe(struct of_device *op, const struct of_device_id *
        leo_init_wids(info);
        leo_init_hw(info);
 
-       leo_blank(0, info);
+       leo_blank(FB_BLANK_UNBLANK, info);
 
        if (fb_alloc_cmap(&info->cmap, 256, 0))
                goto out_unmap_regs;
index c95874fe9076579de587a7c1f87c9ded194ff7b5..676ffb06d1c79784f67a8e66e488dd36a615acda 100644 (file)
@@ -295,7 +295,7 @@ static int __devinit p9100_probe(struct of_device *op, const struct of_device_id
        if (!info->screen_base)
                goto out_unmap_regs;
 
-       p9100_blank(0, info);
+       p9100_blank(FB_BLANK_UNBLANK, info);
 
        if (fb_alloc_cmap(&info->cmap, 256, 0))
                goto out_unmap_screen;
index a71774305772bb8d60270f216b53bd6a996906e5..44e8c27ed0fcd406eaf5af5d2f9cc8b95a062f98 100644 (file)
@@ -84,7 +84,7 @@ struct tcx_tec {
 
 struct tcx_thc {
        u32 thc_rev;
-        u32 thc_pad0[511];
+       u32 thc_pad0[511];
        u32 thc_hs;             /* hsync timing */
        u32 thc_hsdvs;
        u32 thc_hd;
@@ -126,10 +126,10 @@ struct tcx_par {
 };
 
 /* Reset control plane so that WID is 8-bit plane. */
-static void __tcx_set_control_plane (struct tcx_par *par)
+static void __tcx_set_control_plane(struct tcx_par *par)
 {
        u32 __iomem *p, *pend;
-        
+
        if (par->lowdepth)
                return;
 
@@ -143,8 +143,8 @@ static void __tcx_set_control_plane (struct tcx_par *par)
                sbus_writel(tmp, p);
        }
 }
-                                                
-static void tcx_reset (struct fb_info *info)
+
+static void tcx_reset(struct fb_info *info)
 {
        struct tcx_par *par = (struct tcx_par *) info->par;
        unsigned long flags;
@@ -365,7 +365,8 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
                           info->screen_base, par->fbsize);
 }
 
-static int __devinit tcx_init_one(struct of_device *op)
+static int __devinit tcx_probe(struct of_device *op,
+                              const struct of_device_id *match)
 {
        struct device_node *dp = op->node;
        struct fb_info *info;
@@ -488,13 +489,6 @@ out_err:
        return err;
 }
 
-static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match)
-{
-       struct of_device *op = to_of_device(&dev->dev);
-
-       return tcx_init_one(op);
-}
-
 static int __devexit tcx_remove(struct of_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
index d5bd497ab9cbd5154ade0781ed3bffbe3d83aeb7..223b1917093ea357ffe68440199cddd7abdd0489 100644 (file)
@@ -48,7 +48,7 @@ struct affs_ext_key {
  * affs fs inode data in memory
  */
 struct affs_inode_info {
-       u32      i_opencnt;
+       atomic_t i_opencnt;
        struct semaphore i_link_lock;           /* Protects internal inode access. */
        struct semaphore i_ext_lock;            /* Protects internal inode access. */
 #define i_hash_lock i_ext_lock
@@ -170,8 +170,6 @@ extern int  affs_rename(struct inode *old_dir, struct dentry *old_dentry,
 extern unsigned long            affs_parent_ino(struct inode *dir);
 extern struct inode            *affs_new_inode(struct inode *dir);
 extern int                      affs_notify_change(struct dentry *dentry, struct iattr *attr);
-extern void                     affs_put_inode(struct inode *inode);
-extern void                     affs_drop_inode(struct inode *inode);
 extern void                     affs_delete_inode(struct inode *inode);
 extern void                     affs_clear_inode(struct inode *inode);
 extern struct inode            *affs_iget(struct super_block *sb,
index 1a4f092f24efdb2ab13efa4bebb85bd38e7d2678..6eac7bdeec94dc320924d7be0892fb89a23cde72 100644 (file)
@@ -48,8 +48,9 @@ affs_file_open(struct inode *inode, struct file *filp)
 {
        if (atomic_read(&filp->f_count) != 1)
                return 0;
-       pr_debug("AFFS: open(%d)\n", AFFS_I(inode)->i_opencnt);
-       AFFS_I(inode)->i_opencnt++;
+       pr_debug("AFFS: open(%lu,%d)\n",
+                inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
+       atomic_inc(&AFFS_I(inode)->i_opencnt);
        return 0;
 }
 
@@ -58,10 +59,16 @@ affs_file_release(struct inode *inode, struct file *filp)
 {
        if (atomic_read(&filp->f_count) != 0)
                return 0;
-       pr_debug("AFFS: release(%d)\n", AFFS_I(inode)->i_opencnt);
-       AFFS_I(inode)->i_opencnt--;
-       if (!AFFS_I(inode)->i_opencnt)
+       pr_debug("AFFS: release(%lu, %d)\n",
+                inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
+
+       if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
+               mutex_lock(&inode->i_mutex);
+               if (inode->i_size != AFFS_I(inode)->mmu_private)
+                       affs_truncate(inode);
                affs_free_prealloc(inode);
+               mutex_unlock(&inode->i_mutex);
+       }
 
        return 0;
 }
@@ -180,7 +187,7 @@ affs_get_extblock(struct inode *inode, u32 ext)
        /* inline the simplest case: same extended block as last time */
        struct buffer_head *bh = AFFS_I(inode)->i_ext_bh;
        if (ext == AFFS_I(inode)->i_ext_last)
-               atomic_inc(&bh->b_count);
+               get_bh(bh);
        else
                /* we have to do more (not inlined) */
                bh = affs_get_extblock_slow(inode, ext);
@@ -306,7 +313,7 @@ store_ext:
        affs_brelse(AFFS_I(inode)->i_ext_bh);
        AFFS_I(inode)->i_ext_last = ext;
        AFFS_I(inode)->i_ext_bh = bh;
-       atomic_inc(&bh->b_count);
+       get_bh(bh);
 
        return bh;
 
@@ -324,7 +331,6 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
 
        pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
 
-
        BUG_ON(block > (sector_t)0x7fffffffUL);
 
        if (block >= AFFS_I(inode)->i_blkcnt) {
@@ -827,6 +833,8 @@ affs_truncate(struct inode *inode)
                res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
                if (!res)
                        res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
+               else
+                       inode->i_size = AFFS_I(inode)->mmu_private;
                mark_inode_dirty(inode);
                return;
        } else if (inode->i_size == AFFS_I(inode)->mmu_private)
@@ -862,6 +870,7 @@ affs_truncate(struct inode *inode)
                blk++;
        } else
                AFFS_HEAD(ext_bh)->first_data = 0;
+       AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i);
        size = AFFS_SB(sb)->s_hashsize;
        if (size > blkcnt - blk + i)
                size = blkcnt - blk + i;
index 27fe6cbe43ae84bc1582f8e86131cebb1566eb1e..a13b334a391029a60de7426ae1f4684f1fd1f5a3 100644 (file)
@@ -58,7 +58,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
        AFFS_I(inode)->i_extcnt = 1;
        AFFS_I(inode)->i_ext_last = ~1;
        AFFS_I(inode)->i_protect = prot;
-       AFFS_I(inode)->i_opencnt = 0;
+       atomic_set(&AFFS_I(inode)->i_opencnt, 0);
        AFFS_I(inode)->i_blkcnt = 0;
        AFFS_I(inode)->i_lc = NULL;
        AFFS_I(inode)->i_lc_size = 0;
@@ -108,8 +108,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                        inode->i_mode |= S_IFDIR;
                } else
                        inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
-               if (tail->link_chain)
-                       inode->i_nlink = 2;
                /* Maybe it should be controlled by mount parameter? */
                //inode->i_mode |= S_ISVTX;
                inode->i_op = &affs_dir_inode_operations;
@@ -244,32 +242,13 @@ out:
        return error;
 }
 
-void
-affs_put_inode(struct inode *inode)
-{
-       pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
-       affs_free_prealloc(inode);
-}
-
-void
-affs_drop_inode(struct inode *inode)
-{
-       mutex_lock(&inode->i_mutex);
-       if (inode->i_size != AFFS_I(inode)->mmu_private)
-               affs_truncate(inode);
-       mutex_unlock(&inode->i_mutex);
-
-       generic_drop_inode(inode);
-}
-
 void
 affs_delete_inode(struct inode *inode)
 {
        pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
        truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
-       if (S_ISREG(inode->i_mode))
-               affs_truncate(inode);
+       affs_truncate(inode);
        clear_inode(inode);
        affs_free_block(inode->i_sb, inode->i_ino);
 }
@@ -277,9 +256,12 @@ affs_delete_inode(struct inode *inode)
 void
 affs_clear_inode(struct inode *inode)
 {
-       unsigned long cache_page = (unsigned long) AFFS_I(inode)->i_lc;
+       unsigned long cache_page;
 
        pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
+
+       affs_free_prealloc(inode);
+       cache_page = (unsigned long)AFFS_I(inode)->i_lc;
        if (cache_page) {
                pr_debug("AFFS: freeing ext cache\n");
                AFFS_I(inode)->i_lc = NULL;
@@ -316,7 +298,7 @@ affs_new_inode(struct inode *dir)
        inode->i_ino     = block;
        inode->i_nlink   = 1;
        inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       AFFS_I(inode)->i_opencnt = 0;
+       atomic_set(&AFFS_I(inode)->i_opencnt, 0);
        AFFS_I(inode)->i_blkcnt = 0;
        AFFS_I(inode)->i_lc = NULL;
        AFFS_I(inode)->i_lc_size = 0;
@@ -369,12 +351,12 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3
        switch (type) {
        case ST_LINKFILE:
        case ST_LINKDIR:
-               inode_bh = bh;
                retval = -ENOSPC;
                block = affs_alloc_block(dir, dir->i_ino);
                if (!block)
                        goto err;
                retval = -EIO;
+               inode_bh = bh;
                bh = affs_getzeroblk(sb, block);
                if (!bh)
                        goto err;
index 2218f1ee71ce1c2cc146ccd876d614c78fce94cd..cfcf1b6cf82be05dbd9001e494c55cfa26b4b790 100644 (file)
@@ -234,7 +234,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 int
 affs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino,
+       pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino,
+                dentry->d_inode->i_ino,
                 (int)dentry->d_name.len, dentry->d_name.name);
 
        return affs_remove_header(dentry);
@@ -302,7 +303,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 int
 affs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       pr_debug("AFFS: rmdir(dir=%u, \"%.*s\")\n", (u32)dir->i_ino,
+       pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino,
+                dentry->d_inode->i_ino,
                 (int)dentry->d_name.len, dentry->d_name.name);
 
        return affs_remove_header(dentry);
index 01d25d532541bc3d698f5321923a87cf9900cfe4..d214837d5e42a868009d75084e27716f7937e0b2 100644 (file)
@@ -71,12 +71,18 @@ static struct kmem_cache * affs_inode_cachep;
 
 static struct inode *affs_alloc_inode(struct super_block *sb)
 {
-       struct affs_inode_info *ei;
-       ei = (struct affs_inode_info *)kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL);
-       if (!ei)
+       struct affs_inode_info *i;
+
+       i = kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL);
+       if (!i)
                return NULL;
-       ei->vfs_inode.i_version = 1;
-       return &ei->vfs_inode;
+
+       i->vfs_inode.i_version = 1;
+       i->i_lc = NULL;
+       i->i_ext_bh = NULL;
+       i->i_pa_cnt = 0;
+
+       return &i->vfs_inode;
 }
 
 static void affs_destroy_inode(struct inode *inode)
@@ -114,8 +120,6 @@ static const struct super_operations affs_sops = {
        .alloc_inode    = affs_alloc_inode,
        .destroy_inode  = affs_destroy_inode,
        .write_inode    = affs_write_inode,
-       .put_inode      = affs_put_inode,
-       .drop_inode     = affs_drop_inode,
        .delete_inode   = affs_delete_inode,
        .clear_inode    = affs_clear_inode,
        .put_super      = affs_put_super,
index 799f86deff243213256103ee76ff7560098fe965..78562574cb524d87b06883bce5002542b77b5865 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -158,7 +158,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 
                bio_init(bio);
                if (likely(nr_iovecs)) {
-                       unsigned long idx = 0; /* shut up gcc */
+                       unsigned long uninitialized_var(idx);
 
                        bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
                        if (unlikely(!bvl)) {
@@ -963,6 +963,7 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
  *     @data: pointer to buffer to copy
  *     @len: length in bytes
  *     @gfp_mask: allocation flags for bio and page allocation
+ *     @reading: data direction is READ
  *
  *     copy the kernel address into a bio suitable for io to a block
  *     device. Returns an error pointer in case of error.
index bf64781304243f62cc1ff52f9f395724651103d7..c36d9480335c6fc8a099aa1551910b0ce55a539f 100644 (file)
@@ -1149,13 +1149,8 @@ static inline void iput_final(struct inode *inode)
 void iput(struct inode *inode)
 {
        if (inode) {
-               const struct super_operations *op = inode->i_sb->s_op;
-
                BUG_ON(inode->i_state == I_CLEAR);
 
-               if (op && op->put_inode)
-                       op->put_inode(inode);
-
                if (atomic_dec_and_lock(&inode->i_count, &inode_lock))
                        iput_final(inode);
        }
index 663c069b59b3d6490fd2fa9046d4d0bc3620a581..0ac6b92cb0b6365a19a7d4c337362a97b320a0a6 100644 (file)
@@ -1753,6 +1753,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
        struct file_lock *file_lock = locks_alloc_lock();
        struct flock flock;
        struct inode *inode;
+       struct file *f;
        int error;
 
        if (file_lock == NULL)
@@ -1825,7 +1826,15 @@ again:
         * Attempt to detect a close/fcntl race and recover by
         * releasing the lock that was just acquired.
         */
-       if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
+       /*
+        * we need that spin_lock here - it prevents reordering between
+        * update of inode->i_flock and check for it done in close().
+        * rcu_read_lock() wouldn't do.
+        */
+       spin_lock(&current->files->file_lock);
+       f = fcheck(fd);
+       spin_unlock(&current->files->file_lock);
+       if (!error && f != filp && flock.l_type != F_UNLCK) {
                flock.l_type = F_UNLCK;
                goto again;
        }
@@ -1881,6 +1890,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
        struct file_lock *file_lock = locks_alloc_lock();
        struct flock64 flock;
        struct inode *inode;
+       struct file *f;
        int error;
 
        if (file_lock == NULL)
@@ -1953,7 +1963,10 @@ again:
         * Attempt to detect a close/fcntl race and recover by
         * releasing the lock that was just acquired.
         */
-       if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
+       spin_lock(&current->files->file_lock);
+       f = fcheck(fd);
+       spin_unlock(&current->files->file_lock);
+       if (!error && f != filp && flock.l_type != F_UNLCK) {
                flock.l_type = F_UNLCK;
                goto again;
        }
index 3499f9ff6316ba7189475ec11021bab74dcf083a..ec228bc9f8824128ea99c5cb24abc743063e00bb 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -17,6 +17,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/audit.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -1086,8 +1087,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes)
 
        error = do_pipe(fd);
        if (!error) {
-               if (copy_to_user(fildes, fd, sizeof(fd)))
+               if (copy_to_user(fildes, fd, sizeof(fd))) {
+                       sys_close(fd[0]);
+                       sys_close(fd[1]);
                        error = -EFAULT;
+               }
        }
        return error;
 }
index 633f58ebfb72a2ad7b132adb7492f7c268daecca..78150038b58422155b2a89e47e8a228967f0ca3d 100644 (file)
@@ -811,24 +811,19 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 {
        struct address_space *mapping = out->f_mapping;
        struct inode *inode = mapping->host;
-       int killsuid, killpriv;
+       struct splice_desc sd = {
+               .total_len = len,
+               .flags = flags,
+               .pos = *ppos,
+               .u.file = out,
+       };
        ssize_t ret;
-       int err = 0;
-
-       killpriv = security_inode_need_killpriv(out->f_path.dentry);
-       killsuid = should_remove_suid(out->f_path.dentry);
-       if (unlikely(killsuid || killpriv)) {
-               mutex_lock(&inode->i_mutex);
-               if (killpriv)
-                       err = security_inode_killpriv(out->f_path.dentry);
-               if (!err && killsuid)
-                       err = __remove_suid(out->f_path.dentry, killsuid);
-               mutex_unlock(&inode->i_mutex);
-               if (err)
-                       return err;
-       }
 
-       ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+       inode_double_lock(inode, pipe->inode);
+       ret = remove_suid(out->f_path.dentry);
+       if (likely(!ret))
+               ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
+       inode_double_unlock(inode, pipe->inode);
        if (ret > 0) {
                unsigned long nr_pages;
 
@@ -840,6 +835,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
                 * sync it.
                 */
                if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+                       int err;
+
                        mutex_lock(&inode->i_mutex);
                        err = generic_osync_inode(inode, mapping,
                                                  OSYNC_METADATA|OSYNC_DATA);
@@ -1075,7 +1072,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 
        ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
        if (ret > 0)
-               *ppos = sd.pos;
+               *ppos += ret;
 
        return ret;
 }
index 2b34c8ca6c83ed2e6aa01f955664ffccf7eb1ec0..d3231947db19edc3e4e592d3feadd7ab95e2c08a 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/buffer_head.h>
 #include <linux/sched.h>
 #include <linux/crc-itu-t.h>
+#include <linux/exportfs.h>
 
 static inline int udf_match(int len1, const char *name1, int len2,
                            const char *name2)
@@ -158,6 +159,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
        sector_t offset;
        struct extent_position epos = {};
        struct udf_inode_info *dinfo = UDF_I(dir);
+       int isdotdot = dentry->d_name.len == 2 &&
+               dentry->d_name.name[0] == '.' && dentry->d_name.name[1] == '.';
 
        size = udf_ext0_offset(dir) + dir->i_size;
        f_pos = udf_ext0_offset(dir);
@@ -225,6 +228,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
                                continue;
                }
 
+               if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
+                   isdotdot) {
+                       brelse(epos.bh);
+                       return fi;
+               }
+
                if (!lfi)
                        continue;
 
@@ -286,9 +295,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
                }
        }
        unlock_kernel();
-       d_add(dentry, inode);
 
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct fileIdentDesc *udf_add_entry(struct inode *dir,
@@ -307,7 +315,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
        uint16_t liu;
        int block;
        kernel_lb_addr eloc;
-       uint32_t elen;
+       uint32_t elen = 0;
        sector_t offset;
        struct extent_position epos = {};
        struct udf_inode_info *dinfo;
@@ -398,7 +406,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
        }
 
 add:
-       if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+       /* Is there any extent whose size we need to round up? */
+       if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) {
                elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
                        epos.offset -= sizeof(short_ad);
@@ -1232,6 +1241,134 @@ end_rename:
        return retval;
 }
 
+static struct dentry *udf_get_parent(struct dentry *child)
+{
+       struct dentry *parent;
+       struct inode *inode = NULL;
+       struct dentry dotdot;
+       struct fileIdentDesc cfi;
+       struct udf_fileident_bh fibh;
+
+       dotdot.d_name.name = "..";
+       dotdot.d_name.len = 2;
+
+       lock_kernel();
+       if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
+               goto out_unlock;
+
+       if (fibh.sbh != fibh.ebh)
+               brelse(fibh.ebh);
+       brelse(fibh.sbh);
+
+       inode = udf_iget(child->d_inode->i_sb,
+                        lelb_to_cpu(cfi.icb.extLocation));
+       if (!inode)
+               goto out_unlock;
+       unlock_kernel();
+
+       parent = d_alloc_anon(inode);
+       if (!parent) {
+               iput(inode);
+               parent = ERR_PTR(-ENOMEM);
+       }
+
+       return parent;
+out_unlock:
+       unlock_kernel();
+       return ERR_PTR(-EACCES);
+}
+
+
+static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
+                                       u16 partref, __u32 generation)
+{
+       struct inode *inode;
+       struct dentry *result;
+       kernel_lb_addr loc;
+
+       if (block == 0)
+               return ERR_PTR(-ESTALE);
+
+       loc.logicalBlockNum = block;
+       loc.partitionReferenceNum = partref;
+       inode = udf_iget(sb, loc);
+
+       if (inode == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       if (generation && inode->i_generation != generation) {
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       result = d_alloc_anon(inode);
+       if (!result) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       return result;
+}
+
+static struct dentry *udf_fh_to_dentry(struct super_block *sb,
+                                      struct fid *fid, int fh_len, int fh_type)
+{
+       if ((fh_len != 3 && fh_len != 5) ||
+           (fh_type != FILEID_UDF_WITH_PARENT &&
+            fh_type != FILEID_UDF_WITHOUT_PARENT))
+               return NULL;
+
+       return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
+                       fid->udf.generation);
+}
+
+static struct dentry *udf_fh_to_parent(struct super_block *sb,
+                                      struct fid *fid, int fh_len, int fh_type)
+{
+       if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)
+               return NULL;
+
+       return udf_nfs_get_inode(sb, fid->udf.parent_block,
+                                fid->udf.parent_partref,
+                                fid->udf.parent_generation);
+}
+static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
+                        int connectable)
+{
+       int len = *lenp;
+       struct inode *inode =  de->d_inode;
+       kernel_lb_addr location = UDF_I(inode)->i_location;
+       struct fid *fid = (struct fid *)fh;
+       int type = FILEID_UDF_WITHOUT_PARENT;
+
+       if (len < 3 || (connectable && len < 5))
+               return 255;
+
+       *lenp = 3;
+       fid->udf.block = location.logicalBlockNum;
+       fid->udf.partref = location.partitionReferenceNum;
+       fid->udf.generation = inode->i_generation;
+
+       if (connectable && !S_ISDIR(inode->i_mode)) {
+               spin_lock(&de->d_lock);
+               inode = de->d_parent->d_inode;
+               location = UDF_I(inode)->i_location;
+               fid->udf.parent_block = location.logicalBlockNum;
+               fid->udf.parent_partref = location.partitionReferenceNum;
+               fid->udf.parent_generation = inode->i_generation;
+               spin_unlock(&de->d_lock);
+               *lenp = 5;
+               type = FILEID_UDF_WITH_PARENT;
+       }
+
+       return type;
+}
+
+const struct export_operations udf_export_ops = {
+       .encode_fh      = udf_encode_fh,
+       .fh_to_dentry   = udf_fh_to_dentry,
+       .fh_to_parent   = udf_fh_to_parent,
+       .get_parent     = udf_get_parent,
+};
+
 const struct inode_operations udf_dir_inode_operations = {
        .lookup                         = udf_lookup,
        .create                         = udf_create,
index 63610f026ae15046d701d3ab45ab93a04ff51371..96dfd207c3d6339f5a07377a217e5f15c01140e2 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 
-inline uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
-                              uint16_t partition, uint32_t offset)
+uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
+                       uint16_t partition, uint32_t offset)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct udf_part_map *map;
index 9fb18a340fc1efa95fb0acd15d50c89c90652875..7a5f69be6ac2127de968661bd6d5e134712940b3 100644 (file)
@@ -1933,6 +1933,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
        /* Fill in the rest of the superblock */
        sb->s_op = &udf_sb_ops;
+       sb->s_export_op = &udf_export_ops;
        sb->dq_op = NULL;
        sb->s_dirt = 0;
        sb->s_magic = UDF_SUPER_MAGIC;
index f3f45d029277a4f1b038c6baf38ca2cce8703739..8fa9c2d70911701fb6aa0abded2bc86ed439d749 100644 (file)
@@ -73,6 +73,7 @@ struct task_struct;
 struct buffer_head;
 struct super_block;
 
+extern const struct export_operations udf_export_ops;
 extern const struct inode_operations udf_dir_inode_operations;
 extern const struct file_operations udf_dir_operations;
 extern const struct inode_operations udf_file_inode_operations;
index f1b081f53468b0713aef094f3abaaab338c4a72f..73239271873da304c88fe396eda7074686c3185a 100644 (file)
@@ -58,7 +58,7 @@ extern struct mn10300_cpuinfo boot_cpu_data;
 extern void identify_cpu(struct mn10300_cpuinfo *);
 extern void print_cpu_info(struct mn10300_cpuinfo *);
 extern void dodgy_tsc(void);
-#define cpu_relax() do {} while (0)
+#define cpu_relax() barrier()
 
 /*
  * User space process size: 1.75GB (default).
index f8204a4f2e0260917655a7877f126e9a53cd2186..18cbd8a39796c126fb9e1609f333c516d86a2e9d 100644 (file)
@@ -104,6 +104,7 @@ struct sie_block {
 
 struct kvm_vcpu_stat {
        u32 exit_userspace;
+       u32 exit_null;
        u32 exit_external_request;
        u32 exit_external_interrupt;
        u32 exit_stop_request;
index f0f4579eac13144b01f43eaf401428dfb2d8c5db..12fd9c4f0f154fe86baaed66c71103d24b15f65a 100644 (file)
@@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr)
        return skey;
 }
 
+#ifdef CONFIG_PAGE_STATES
+
+struct page;
+void arch_free_page(struct page *page, int order);
+void arch_alloc_page(struct page *page, int order);
+
+#define HAVE_ARCH_FREE_PAGE
+#define HAVE_ARCH_ALLOC_PAGE
+
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
index 441d7c260857845cd6e0e1b557277565c448a2cd..d7d4e2eb3e6f327b8528387d2f1a3822fc8820c6 100644 (file)
@@ -471,6 +471,8 @@ struct task_struct;
 extern void user_enable_single_step(struct task_struct *);
 extern void user_disable_single_step(struct task_struct *);
 
+#define __ARCH_WANT_COMPAT_SYS_PTRACE
+
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
 #define regs_return_value(regs)((regs)->gprs[2])
index c819ae25a8425ddfd72136dda4d674bf0f8b0ac1..e0d4500d5f95c14478205c60269849a8d5852ace 100644 (file)
@@ -116,6 +116,12 @@ extern void pfault_fini(void);
 #define pfault_fini()          do { } while (0)
 #endif /* CONFIG_PFAULT */
 
+#ifdef CONFIG_PAGE_STATES
+extern void cmma_init(void);
+#else
+static inline void cmma_init(void) { }
+#endif
+
 #define finish_arch_switch(prev) do {                                       \
        set_fs(current->thread.mm_segment);                                  \
        account_vtime(prev);                                                 \
index 577ab79c4c27b8ebaa84542806dfe4d3f217553f..d7f0403bbecb89a31c9097e79392c4c9b0c7eae5 100644 (file)
@@ -88,14 +88,7 @@ extern unsigned long pg0[];
 /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
 #define pmd_none(x)    (!(unsigned long)pmd_val((x)))
 #define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT)
-
-extern int pmd_bad(pmd_t pmd);
-
-#define pmd_bad_v1(x)                                                  \
-       (_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER)))
-#define        pmd_bad_v2(x)                                                   \
-       (_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER |    \
-                                           _PAGE_PSE | _PAGE_NX)))
+#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
index a3bbf8766c1d62790d2f999bba1edac5dab7fa64..efe83dcbd41200fc6822a96ebea1a678fe452ef1 100644 (file)
@@ -158,14 +158,12 @@ static inline unsigned long pgd_bad(pgd_t pgd)
 
 static inline unsigned long pud_bad(pud_t pud)
 {
-       return pud_val(pud) &
-               ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+       return pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
 }
 
 static inline unsigned long pmd_bad(pmd_t pmd)
 {
-       return pmd_val(pmd) &
-               ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+       return pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
 }
 
 #define pte_none(x)    (!pte_val((x)))
index de8387b7ceb6cd85ab872c3fe5e5f62c366af260..f5abd1306638379ecd609512cc742b8af53169e3 100644 (file)
@@ -33,6 +33,19 @@ enum fid_type {
         * 32 bit parent directory inode number.
         */
        FILEID_INO32_GEN_PARENT = 2,
+
+       /*
+        * 32 bit block number, 16 bit partition reference,
+        * 16 bit unused, 32 bit generation number.
+        */
+       FILEID_UDF_WITHOUT_PARENT = 0x51,
+
+       /*
+        * 32 bit block number, 16 bit partition reference,
+        * 16 bit unused, 32 bit generation number,
+        * 32 bit parent block number, 32 bit parent generation number
+        */
+       FILEID_UDF_WITH_PARENT = 0x52,
 };
 
 struct fid {
@@ -43,6 +56,14 @@ struct fid {
                        u32 parent_ino;
                        u32 parent_gen;
                } i32;
+               struct {
+                       u32 block;
+                       u16 partref;
+                       u16 parent_partref;
+                       u32 generation;
+                       u32 parent_block;
+                       u32 parent_generation;
+               } udf;
                __u32 raw[0];
        };
 };
index a1ba005d08e7ef80f441d00a7f5d934582fe13e6..f413085f748e574140ca4216abbb303209cc7fb0 100644 (file)
@@ -1289,17 +1289,12 @@ extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
 extern ssize_t vfs_writev(struct file *, const struct iovec __user *,
                unsigned long, loff_t *);
 
-/*
- * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called
- * without the big kernel lock held in all filesystems.
- */
 struct super_operations {
        struct inode *(*alloc_inode)(struct super_block *sb);
        void (*destroy_inode)(struct inode *);
 
        void (*dirty_inode) (struct inode *);
        int (*write_inode) (struct inode *, int);
-       void (*put_inode) (struct inode *);
        void (*drop_inode) (struct inode *);
        void (*delete_inode) (struct inode *);
        void (*put_super) (struct super_block *);
@@ -1821,7 +1816,6 @@ extern void iget_failed(struct inode *);
 extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
-extern int __remove_suid(struct dentry *, int);
 extern int should_remove_suid(struct dentry *);
 extern int remove_suid(struct dentry *);
 
index ecd2bf63fc849e201f4825010293ba20a736d09b..e9874e7fcdf90c04cea4c18cae9574bbd5e50e89 100644 (file)
@@ -178,17 +178,17 @@ static inline struct hd_struct *get_part(struct gendisk *gendiskp,
 
 static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)      {
        int i;
+
        for_each_possible_cpu(i)
                memset(per_cpu_ptr(gendiskp->dkstats, i), value,
-                               sizeof (struct disk_stats));
+                               sizeof(struct disk_stats));
 }              
 
 #define __part_stat_add(part, field, addnd)                            \
        (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd)
 
-#define __all_stat_add(gendiskp, field, addnd, sector)         \
+#define __all_stat_add(gendiskp, part, field, addnd, sector)   \
 ({                                                             \
-       struct hd_struct *part = get_part(gendiskp, sector);    \
        if (part)                                               \
                __part_stat_add(part, field, addnd);            \
        __disk_stat_add(gendiskp, field, addnd);                \
@@ -203,11 +203,13 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
        res;                                                            \
 })
 
-static inline void part_stat_set_all(struct hd_struct *part, int value)        {
+static inline void part_stat_set_all(struct hd_struct *part, int value)
+{
        int i;
+
        for_each_possible_cpu(i)
                memset(per_cpu_ptr(part->dkstats, i), value,
-                      sizeof(struct disk_stats));
+                               sizeof(struct disk_stats));
 }
                                
 #else /* !CONFIG_SMP */
@@ -223,9 +225,8 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)
 #define __part_stat_add(part, field, addnd) \
        (part->dkstats.field += addnd)
 
-#define __all_stat_add(gendiskp, field, addnd, sector)         \
+#define __all_stat_add(gendiskp, part, field, addnd, sector)   \
 ({                                                             \
-       struct hd_struct *part = get_part(gendiskp, sector);    \
        if (part)                                               \
                part->dkstats.field += addnd;                   \
        __disk_stat_add(gendiskp, field, addnd);                \
@@ -276,10 +277,10 @@ static inline void part_stat_set_all(struct hd_struct *part, int value)
 #define part_stat_sub(gendiskp, field, subnd) \
                part_stat_add(gendiskp, field, -subnd)
 
-#define all_stat_add(gendiskp, field, addnd, sector)           \
+#define all_stat_add(gendiskp, part, field, addnd, sector)     \
        do {                                                    \
                preempt_disable();                              \
-               __all_stat_add(gendiskp, field, addnd, sector); \
+               __all_stat_add(gendiskp, part, field, addnd, sector);   \
                preempt_enable();                               \
        } while (0)
 
@@ -288,15 +289,15 @@ static inline void part_stat_set_all(struct hd_struct *part, int value)
 #define all_stat_dec(gendiskp, field, sector) \
                all_stat_add(gendiskp, field, -1, sector)
 
-#define __all_stat_inc(gendiskp, field, sector) \
-               __all_stat_add(gendiskp, field, 1, sector)
-#define all_stat_inc(gendiskp, field, sector) \
-               all_stat_add(gendiskp, field, 1, sector)
+#define __all_stat_inc(gendiskp, part, field, sector) \
+               __all_stat_add(gendiskp, part, field, 1, sector)
+#define all_stat_inc(gendiskp, part, field, sector) \
+               all_stat_add(gendiskp, part, field, 1, sector)
 
-#define __all_stat_sub(gendiskp, field, subnd, sector) \
-               __all_stat_add(gendiskp, field, -subnd, sector)
-#define all_stat_sub(gendiskp, field, subnd, sector) \
-               all_stat_add(gendiskp, field, -subnd, sector)
+#define __all_stat_sub(gendiskp, part, field, subnd, sector) \
+               __all_stat_add(gendiskp, part, field, -subnd, sector)
+#define all_stat_sub(gendiskp, part, field, subnd, sector) \
+               all_stat_add(gendiskp, part, field, -subnd, sector)
 
 /* Inlines to alloc and free disk stats in struct gendisk */
 #ifdef  CONFIG_SMP
index 2a3bb1bb74336f27c27f6627153900d46d6c178a..f98a656b17e5b4b732e57e0e70e4eb5ec53bce84 100644 (file)
@@ -67,6 +67,20 @@ static inline int task_nice_ioprio(struct task_struct *task)
        return (task_nice(task) + 20) / 5;
 }
 
+/*
+ * This is for the case where the task hasn't asked for a specific IO class.
+ * Check for idle and rt task process, and return appropriate IO class.
+ */
+static inline int task_nice_ioclass(struct task_struct *task)
+{
+       if (task->policy == SCHED_IDLE)
+               return IOPRIO_CLASS_IDLE;
+       else if (task->policy == SCHED_FIFO || task->policy == SCHED_RR)
+               return IOPRIO_CLASS_RT;
+       else
+               return IOPRIO_CLASS_BE;
+}
+
 /*
  * For inheritance, return the highest of the two given priorities
  */
index d1dfe872ee308f854a4b7dd2113e124c4813d1ab..7e206da1fbfb4e88807b0609bdb814b38d247ebe 100644 (file)
@@ -1039,6 +1039,7 @@ extern void ata_eh_thaw_port(struct ata_port *ap);
 
 extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
+extern void ata_eh_analyze_ncq_error(struct ata_link *link);
 
 extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
                      ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
@@ -1381,6 +1382,21 @@ static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
        return *(struct ata_port **)&host->hostdata[0];
 }
 
+static inline int ata_check_ready(u8 status)
+{
+       /* Some controllers report 0x77 or 0x7f during intermediate
+        * not-ready stages.
+        */
+       if (status == 0x77 || status == 0x7f)
+               return 0;
+
+       /* 0xff indicates either no device or device not ready */
+       if (status == 0xff)
+               return -ENODEV;
+
+       return !(status & ATA_BUSY);
+}
+
 
 /**************************************************************************
  * PMP - drivers/ata/libata-pmp.c
index 6d7bcd5e62d48ce689b1700afa9e34a82401e86e..3b40bc2234becd9099dc2e5bb70d352474a04210 100644 (file)
@@ -210,7 +210,7 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
 {
        return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
                (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
-                !(dst_metric(dst, RTAX_LOCK)&(1<<RTAX_MTU))));
+                !(dst_metric_locked(dst, RTAX_MTU))));
 }
 
 extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
index d1350bcccb03c68efb07bac000b16c0f9cb49ca1..2933d7474a79541a8de4c38e53e3b2b2f6f9ca77 100644 (file)
@@ -648,14 +648,46 @@ extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
 extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
                                     struct sk_buff *skb, u8 proto);
 #else
-#define xfrm_audit_policy_add(x, r, a, se, s)  do { ; } while (0)
-#define xfrm_audit_policy_delete(x, r, a, se, s)       do { ; } while (0)
-#define xfrm_audit_state_add(x, r, a, se, s)   do { ; } while (0)
-#define xfrm_audit_state_delete(x, r, a, se, s)        do { ; } while (0)
-#define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0)
-#define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0)
-#define xfrm_audit_state_notfound(s, f, sp, sq)        do { ; } while (0)
-#define xfrm_audit_state_icvfail(x, s, p)      do { ; } while (0)
+
+static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+                                 u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+                                 u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_add(struct xfrm_state *x, int result,
+                                u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+                                   u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+                                            struct sk_buff *skb)
+{
+}
+
+static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
+                                     u16 family)
+{
+}
+
+static inline void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
+                                     __be32 net_spi, __be32 net_seq)
+{
+}
+
+static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
+                                    struct sk_buff *skb, u8 proto)
+{
+}
 #endif /* CONFIG_AUDITSYSCALL */
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
index 8da627d33804db7c9e30936fead573cedd4407e3..86ea9e34e3260138401663be21dd22d1892c4ce3 100644 (file)
@@ -1031,11 +1031,9 @@ int current_cpuset_is_being_rebound(void)
        return task_cs(current) == cpuset_being_rebound;
 }
 
-static int update_relax_domain_level(struct cpuset *cs, char *buf)
+static int update_relax_domain_level(struct cpuset *cs, s64 val)
 {
-       int val = simple_strtol(buf, NULL, 10);
-
-       if (val < 0)
+       if ((int)val < 0)
                val = -1;
 
        if (val != cs->relax_domain_level) {
@@ -1280,9 +1278,6 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
        case FILE_MEMLIST:
                retval = update_nodemask(cs, buffer);
                break;
-       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
-               retval = update_relax_domain_level(cs, buffer);
-               break;
        default:
                retval = -EINVAL;
                goto out2;
@@ -1348,6 +1343,30 @@ static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
        return retval;
 }
 
+static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
+{
+       int retval = 0;
+       struct cpuset *cs = cgroup_cs(cgrp);
+       cpuset_filetype_t type = cft->private;
+
+       cgroup_lock();
+
+       if (cgroup_is_removed(cgrp)) {
+               cgroup_unlock();
+               return -ENODEV;
+       }
+       switch (type) {
+       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
+               retval = update_relax_domain_level(cs, val);
+               break;
+       default:
+               retval = -EINVAL;
+               break;
+       }
+       cgroup_unlock();
+       return retval;
+}
+
 /*
  * These ascii lists should be read in a single call, by using a user
  * buffer large enough to hold the entire map.  If read in smaller
@@ -1406,9 +1425,6 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
        case FILE_MEMLIST:
                s += cpuset_sprintf_memlist(s, cs);
                break;
-       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
-               s += sprintf(s, "%d", cs->relax_domain_level);
-               break;
        default:
                retval = -EINVAL;
                goto out;
@@ -1449,6 +1465,18 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
        }
 }
 
+static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
+{
+       struct cpuset *cs = cgroup_cs(cont);
+       cpuset_filetype_t type = cft->private;
+       switch (type) {
+       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
+               return cs->relax_domain_level;
+       default:
+               BUG();
+       }
+}
+
 
 /*
  * for the common functions, 'private' gives the type of file
@@ -1499,8 +1527,8 @@ static struct cftype files[] = {
 
        {
                .name = "sched_relax_domain_level",
-               .read_u64 = cpuset_read_u64,
-               .write_u64 = cpuset_write_u64,
+               .read_s64 = cpuset_read_s64,
+               .write_s64 = cpuset_write_s64,
                .private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
        },
 
index 7de644cdec43590be390d3037206e5722aa46856..bc24dcdc570f5dfa222edbff1c1a2d80e23cb7e1 100644 (file)
@@ -1191,7 +1191,7 @@ static ssize_t relay_file_splice_read(struct file *in,
        ret = 0;
        spliced = 0;
 
-       while (len && !spliced) {
+       while (len) {
                ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
                if (ret < 0)
                        break;
index 239d36163bbe53fbb2115595e82ed9aef3180b02..2dead9adf8b76806e66ac1b0169510773be58e14 100644 (file)
@@ -1655,7 +1655,7 @@ int should_remove_suid(struct dentry *dentry)
 }
 EXPORT_SYMBOL(should_remove_suid);
 
-int __remove_suid(struct dentry *dentry, int kill)
+static int __remove_suid(struct dentry *dentry, int kill)
 {
        struct iattr newattrs;
 
index bbab1e37055e22df235af61ddd201fe4b9832283..48c122d42ed743dcc90178170b4aff380ec3ad8c 100644 (file)
@@ -969,7 +969,7 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                goto no_page_table;
        
        pmd = pmd_offset(pud, address);
-       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+       if (pmd_none(*pmd))
                goto no_page_table;
 
        if (pmd_huge(*pmd)) {
@@ -978,6 +978,9 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                goto out;
        }
 
+       if (unlikely(pmd_bad(*pmd)))
+               goto no_page_table;
+
        ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
        if (!ptep)
                goto out;
index d379b782fc8325cec775bc1daca939bbe06d6d75..a505a828ef411e08f149a413fb37f32da7c47e21 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3762,7 +3762,7 @@ static int any_slab_objects(struct kmem_cache *s)
                if (!n)
                        continue;
 
-               if (atomic_read(&n->total_objects))
+               if (atomic_long_read(&n->total_objects))
                        return 1;
        }
        return 0;
index 1b228065e745c812ee8db3d6ca0b3bb68586b796..9d52ebfc1962b360774f55e728b32ea0d8388654 100644 (file)
@@ -346,9 +346,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                /* skb==NULL means VCC is being destroyed */
                br2684_close_vcc(brvcc);
                if (list_empty(&brdev->brvccs)) {
-                       read_lock(&devs_lock);
+                       write_lock_irq(&devs_lock);
                        list_del(&brdev->br2684_devs);
-                       read_unlock(&devs_lock);
+                       write_unlock_irq(&devs_lock);
                        unregister_netdev(net_dev);
                        free_netdev(net_dev);
                }
index 77a981a1ee52249d5fbed7966f294afe7730ffb3..c2397f503b0f94e850d7da40b68e53fb16b9f9ae 100644 (file)
@@ -273,15 +273,13 @@ int br_add_bridge(const char *name)
        rtnl_lock();
        if (strchr(dev->name, '%')) {
                ret = dev_alloc_name(dev, dev->name);
-               if (ret < 0) {
-                       free_netdev(dev);
-                       goto out;
-               }
+               if (ret < 0)
+                       goto out_free;
        }
 
        ret = register_netdevice(dev);
        if (ret)
-               goto out;
+               goto out_free;
 
        ret = br_sysfs_addbr(dev);
        if (ret)
@@ -289,6 +287,10 @@ int br_add_bridge(const char *name)
  out:
        rtnl_unlock();
        return ret;
+
+out_free:
+       free_netdev(dev);
+       goto out;
 }
 
 int br_del_bridge(const char *name)
index 4fe605fa6f8a27dd2c346bedcb78caa09fdf8e81..5c459f2b7985211e0dd8d067e925c20f2e35b958 100644 (file)
@@ -200,7 +200,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
                goto nodata;
 
        /*
-        * See comment in sk_buff definition, just before the 'tail' member
+        * Only clear those fields we need to clear, not those that we will
+        * actually initialise below. Hence, don't put any more fields after
+        * the tail pointer in struct sk_buff!
         */
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = size + sizeof(struct sk_buff);
index 4a4f6ce4498d42c77dde9b7a5867575210931b31..933a0ecf8d463b0649fd69f78335533d86950517 100644 (file)
@@ -32,7 +32,7 @@ int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
 
        if (len > 3) {
                DCCP_WARN("invalid length %d\n", len);
-               return 1;
+               return -EINVAL;
        }
        /* XXX add further sanity checks */
 
index 2f665a516476a019460046d61195310aecf5654a..f50e88bf2661b5cb3f353433007aad7415410ab4 100644 (file)
@@ -235,14 +235,14 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
        else
                min_mtu -= 21;
 
-       if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= min_mtu) {
+       if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) {
                if (!(dst_metric_locked(dst, RTAX_MTU))) {
                        dst->metrics[RTAX_MTU-1] = mtu;
                        dst_set_expires(dst, dn_rt_mtu_expires);
                }
                if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
                        u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
-                       if (dst->metrics[RTAX_ADVMSS-1] > mss)
+                       if (dst_metric(dst, RTAX_ADVMSS) > mss)
                                dst->metrics[RTAX_ADVMSS-1] = mss;
                }
        }
@@ -805,12 +805,12 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
                rt->u.dst.neighbour = n;
        }
 
-       if (rt->u.dst.metrics[RTAX_MTU-1] == 0 ||
-           rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu)
+       if (dst_metric(&rt->u.dst, RTAX_MTU) == 0 ||
+           dst_metric(&rt->u.dst, RTAX_MTU) > rt->u.dst.dev->mtu)
                rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
        mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->u.dst));
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0 ||
-           rt->u.dst.metrics[RTAX_ADVMSS-1] > mss)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) == 0 ||
+           dst_metric(&rt->u.dst, RTAX_ADVMSS) > mss)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = mss;
        return 0;
 }
index 5e3685c5c407ac2e6b24c13eaf055319d2d341aa..92f90ae46f4a3cc453ebf17c3a97d1df508394a6 100644 (file)
@@ -1468,14 +1468,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
 
                                        /* BSD 4.2 compatibility hack :-( */
                                        if (mtu == 0 &&
-                                           old_mtu >= rth->u.dst.metrics[RTAX_MTU-1] &&
+                                           old_mtu >= dst_metric(&rth->u.dst, RTAX_MTU) &&
                                            old_mtu >= 68 + (iph->ihl << 2))
                                                old_mtu -= iph->ihl << 2;
 
                                        mtu = guess_mtu(old_mtu);
                                }
-                               if (mtu <= rth->u.dst.metrics[RTAX_MTU-1]) {
-                                       if (mtu < rth->u.dst.metrics[RTAX_MTU-1]) {
+                               if (mtu <= dst_metric(&rth->u.dst, RTAX_MTU)) {
+                                       if (mtu < dst_metric(&rth->u.dst, RTAX_MTU)) {
                                                dst_confirm(&rth->u.dst);
                                                if (mtu < ip_rt_min_pmtu) {
                                                        mtu = ip_rt_min_pmtu;
@@ -1497,7 +1497,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
 
 static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
-       if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
+       if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= 68 &&
            !(dst_metric_locked(dst, RTAX_MTU))) {
                if (mtu < ip_rt_min_pmtu) {
                        mtu = ip_rt_min_pmtu;
@@ -1613,7 +1613,7 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
                       sizeof(rt->u.dst.metrics));
                if (fi->fib_mtu == 0) {
                        rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
-                       if (rt->u.dst.metrics[RTAX_LOCK-1] & (1 << RTAX_MTU) &&
+                       if (dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
                            rt->rt_gateway != rt->rt_dst &&
                            rt->u.dst.dev->mtu > 576)
                                rt->u.dst.metrics[RTAX_MTU-1] = 576;
@@ -1624,14 +1624,14 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
        } else
                rt->u.dst.metrics[RTAX_MTU-1]= rt->u.dst.dev->mtu;
 
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
                rt->u.dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
-       if (rt->u.dst.metrics[RTAX_MTU-1] > IP_MAX_MTU)
+       if (dst_metric(&rt->u.dst, RTAX_MTU) > IP_MAX_MTU)
                rt->u.dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) == 0)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->u.dst.dev->mtu - 40,
                                       ip_rt_min_advmss);
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] > 65535 - 40)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535 - 40)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535 - 40;
 
 #ifdef CONFIG_NET_CLS_ROUTE
index eda4f4a233f36e940fe81cf83188dcbc2817e0fa..8ac15a604e086b766552b3ff8a646ca3a8d44f08 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sysctl.h>
+#include <net/dst.h>
 #include <net/tcp.h>
 #include <net/inet_common.h>
 #include <linux/ipsec.h>
@@ -605,7 +606,7 @@ static u32 tcp_rto_min(struct sock *sk)
        u32 rto_min = TCP_RTO_MIN;
 
        if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
-               rto_min = dst->metrics[RTAX_RTO_MIN - 1];
+               rto_min = dst_metric(dst, RTAX_RTO_MIN);
        return rto_min;
 }
 
@@ -769,7 +770,7 @@ void tcp_update_metrics(struct sock *sk)
                                dst->metrics[RTAX_RTTVAR - 1] = m;
                        else
                                dst->metrics[RTAX_RTTVAR-1] -=
-                                       (dst->metrics[RTAX_RTTVAR-1] - m)>>2;
+                                       (dst_metric(dst, RTAX_RTTVAR) - m)>>2;
                }
 
                if (tp->snd_ssthresh >= 0xFFFF) {
@@ -788,21 +789,21 @@ void tcp_update_metrics(struct sock *sk)
                                dst->metrics[RTAX_SSTHRESH-1] =
                                        max(tp->snd_cwnd >> 1, tp->snd_ssthresh);
                        if (!dst_metric_locked(dst, RTAX_CWND))
-                               dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_cwnd) >> 1;
+                               dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_cwnd) >> 1;
                } else {
                        /* Else slow start did not finish, cwnd is non-sense,
                           ssthresh may be also invalid.
                         */
                        if (!dst_metric_locked(dst, RTAX_CWND))
-                               dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_ssthresh) >> 1;
-                       if (dst->metrics[RTAX_SSTHRESH-1] &&
+                               dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_ssthresh) >> 1;
+                       if (dst_metric(dst, RTAX_SSTHRESH) &&
                            !dst_metric_locked(dst, RTAX_SSTHRESH) &&
-                           tp->snd_ssthresh > dst->metrics[RTAX_SSTHRESH-1])
+                           tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH))
                                dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh;
                }
 
                if (!dst_metric_locked(dst, RTAX_REORDERING)) {
-                       if (dst->metrics[RTAX_REORDERING-1] < tp->reordering &&
+                       if (dst_metric(dst, RTAX_REORDERING) < tp->reordering &&
                            tp->reordering != sysctl_tcp_reordering)
                                dst->metrics[RTAX_REORDERING-1] = tp->reordering;
                }
index a493ad9b891475bdd7cd0c11b18688d8fe306f31..12bba0880345474e13a02bf42f6ab44cdbeb19e7 100644 (file)
@@ -1243,11 +1243,11 @@ install_route:
                }
        }
 
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
                rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
-       if (!rt->u.dst.metrics[RTAX_MTU-1])
+       if (!dst_metric(&rt->u.dst, RTAX_MTU))
                rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
-       if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
+       if (!dst_metric(&rt->u.dst, RTAX_ADVMSS))
                rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
        rt->u.dst.dev = dev;
        rt->rt6i_idev = idev;
index 9ad4e3631b6bd4b5ac012f53457abcaa41e2ec47..915afadb06028b270e7229074a325c66836a3e85 100644 (file)
@@ -1766,6 +1766,7 @@ fail_wep:
 fail_rate:
        ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
        unregister_netdevice(local->mdev);
+       local->mdev = NULL;
 fail_dev:
        rtnl_unlock();
        sta_info_stop(local);
@@ -1773,8 +1774,10 @@ fail_sta_info:
        debugfs_hw_del(local);
        destroy_workqueue(local->hw.workqueue);
 fail_workqueue:
-       ieee80211_if_free(local->mdev);
-       local->mdev = NULL;
+       if (local->mdev != NULL) {
+               ieee80211_if_free(local->mdev);
+               local->mdev = NULL;
+       }
 fail_mdev_alloc:
        wiphy_unregister(local->hw.wiphy);
        return result;
index ae75d417873988c3b9edcaff38d83b8d97af2153..ff5c380f3c1343805108b1d561ed931161a8e20e 100644 (file)
@@ -85,7 +85,7 @@ static int rate_control_pid_events_open(struct inode *inode, struct file *file)
        struct rc_pid_sta_info *sinfo = inode->i_private;
        struct rc_pid_event_buffer *events = &sinfo->events;
        struct rc_pid_events_file_info *file_info;
-       unsigned int status;
+       unsigned long status;
 
        /* Allocate a state struct */
        file_info = kmalloc(sizeof(*file_info), GFP_KERNEL);
@@ -135,7 +135,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf,
        char pb[RC_PID_PRINT_BUF_SIZE];
        int ret;
        int p;
-       unsigned int status;
+       unsigned long status;
 
        /* Check if there is something to read. */
        if (events->next_entry == file_info->next_entry) {
index 64b2d136c78e9ac1cf370e3289bed361de9995ff..1d421d059caf48aa7f2327acf0c011355deaf534 100644 (file)
@@ -6,7 +6,7 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
- * Authors:    Jamal Hadi Salim (2005)
+ * Authors:    Jamal Hadi Salim (2005-8)
  *
  */
 
@@ -34,6 +34,7 @@ static struct tcf_hashinfo simp_hash_info = {
        .lock   =       &simp_lock,
 };
 
+#define SIMP_MAX_DATA  32
 static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
 {
        struct tcf_defact *d = a->priv;
@@ -69,23 +70,28 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
        return ret;
 }
 
-static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
+static int alloc_defdata(struct tcf_defact *d, char *defdata)
 {
-       d->tcfd_defdata = kmemdup(defdata, datalen, GFP_KERNEL);
+       d->tcfd_defdata = kstrndup(defdata, SIMP_MAX_DATA, GFP_KERNEL);
        if (unlikely(!d->tcfd_defdata))
                return -ENOMEM;
-       d->tcfd_datalen = datalen;
+
        return 0;
 }
 
-static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
+static void reset_policy(struct tcf_defact *d, char *defdata,
+                        struct tc_defact *p)
 {
-       kfree(d->tcfd_defdata);
-       return alloc_defdata(d, datalen, defdata);
+       spin_lock_bh(&d->tcf_lock);
+       d->tcf_action = p->action;
+       memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
+       strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+       spin_unlock_bh(&d->tcf_lock);
 }
 
 static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
        [TCA_DEF_PARMS] = { .len = sizeof(struct tc_defact) },
+       [TCA_DEF_DATA]  = { .type = NLA_STRING, .len = SIMP_MAX_DATA },
 };
 
 static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
@@ -95,28 +101,24 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
        struct tc_defact *parm;
        struct tcf_defact *d;
        struct tcf_common *pc;
-       void *defdata;
-       u32 datalen = 0;
+       char *defdata;
        int ret = 0, err;
 
        if (nla == NULL)
                return -EINVAL;
 
-       err = nla_parse_nested(tb, TCA_DEF_MAX, nla, NULL);
+       err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy);
        if (err < 0)
                return err;
 
        if (tb[TCA_DEF_PARMS] == NULL)
                return -EINVAL;
 
-       parm = nla_data(tb[TCA_DEF_PARMS]);
-       defdata = nla_data(tb[TCA_DEF_DATA]);
-       if (defdata == NULL)
+       if (tb[TCA_DEF_DATA] == NULL)
                return -EINVAL;
 
-       datalen = nla_len(tb[TCA_DEF_DATA]);
-       if (datalen == 0)
-               return -EINVAL;
+       parm = nla_data(tb[TCA_DEF_PARMS]);
+       defdata = nla_data(tb[TCA_DEF_DATA]);
 
        pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
        if (!pc) {
@@ -126,11 +128,12 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
                        return -ENOMEM;
 
                d = to_defact(pc);
-               ret = alloc_defdata(d, datalen, defdata);
+               ret = alloc_defdata(d, defdata);
                if (ret < 0) {
                        kfree(pc);
                        return ret;
                }
+               d->tcf_action = parm->action;
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
@@ -138,13 +141,9 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
                        tcf_simp_release(d, bind);
                        return -EEXIST;
                }
-               realloc_defdata(d, datalen, defdata);
+               reset_policy(d, defdata, parm);
        }
 
-       spin_lock_bh(&d->tcf_lock);
-       d->tcf_action = parm->action;
-       spin_unlock_bh(&d->tcf_lock);
-
        if (ret == ACT_P_CREATED)
                tcf_hash_insert(pc, &simp_hash_info);
        return ret;
@@ -172,7 +171,7 @@ static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
        opt.bindcnt = d->tcf_bindcnt - bind;
        opt.action = d->tcf_action;
        NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
-       NLA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata);
+       NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata);
        t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
        t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
        t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
index 66148cc4759ee862a848a1d802d04e13dd89b290..5bc1ed4901800af63fc1255ba1f5eecbbe8368de 100644 (file)
@@ -1197,12 +1197,16 @@ static inline int htb_parent_last_child(struct htb_class *cl)
        return 1;
 }
 
-static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q)
+static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
+                              struct Qdisc *new_q)
 {
        struct htb_class *parent = cl->parent;
 
        BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
 
+       if (parent->cmode != HTB_CAN_SEND)
+               htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
+
        parent->level = 0;
        memset(&parent->un.inner, 0, sizeof(parent->un.inner));
        INIT_LIST_HEAD(&parent->un.leaf.drop_list);
@@ -1300,7 +1304,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
                htb_deactivate(q, cl);
 
        if (last_child)
-               htb_parent_to_leaf(cl, new_q);
+               htb_parent_to_leaf(q, cl, new_q);
 
        if (--cl->refcnt == 0)
                htb_destroy_class(sch, cl);
index dfe670f12e67d71117904db746c2a2b8e87af10d..eb9bc365530dde4107f1cf4f9de102bd66dac59b 100644 (file)
@@ -67,7 +67,7 @@ static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id
                return 1;
        
        mem = ioremap(base, 128);
-       if(mem == 0UL)
+       if (!mem)
                return 1;
        map = readw(mem + 0x18);        /* Read the SMI enables */
        iounmap(mem);