]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Aug 2010 00:59:09 +0000 (17:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Aug 2010 00:59:09 +0000 (17:59 -0700)
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] acpi-cpufreq: add missing __percpu markup

195 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
Makefile
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/arm/kernel/sys_arm.c
arch/arm/kernel/sys_oabi-compat.c
arch/avr32/include/asm/syscalls.h
arch/avr32/kernel/process.c
arch/blackfin/kernel/process.c
arch/frv/kernel/process.c
arch/h8300/kernel/process.c
arch/ia64/include/asm/unistd.h
arch/ia64/kernel/process.c
arch/m32r/kernel/process.c
arch/m68k/kernel/process.c
arch/m68knommu/kernel/process.c
arch/microblaze/kernel/sys_microblaze.c
arch/mips/kernel/syscall.c
arch/mn10300/kernel/process.c
arch/parisc/hpux/fs.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/sys_ppc32.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/include/asm/unistd.h
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/entry.h
arch/s390/kernel/process.c
arch/s390/kernel/sys_s390.c
arch/s390/kernel/syscalls.S
arch/sh/include/asm/syscalls_32.h
arch/sh/include/asm/syscalls_64.h
arch/sh/kernel/process_64.c
arch/sparc/kernel/sys_sparc32.c
arch/um/kernel/exec.c
arch/um/kernel/internal.h
arch/um/kernel/syscall.c
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/page.h
arch/x86/include/asm/sys_ia32.h
arch/x86/include/asm/syscalls.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/mpparse.c
arch/x86/kernel/process.c
arch/x86/kernel/tlb_uv.c
arch/x86/lib/atomic64_386_32.S
arch/x86/mm/fault.c
arch/x86/oprofile/nmi_int.c
arch/xtensa/kernel/process.c
drivers/crypto/Kconfig
drivers/input/joystick/amijoy.c
drivers/input/keyboard/hil_kbd.c
drivers/isdn/hardware/avm/c4.c
drivers/isdn/hardware/avm/t1pci.c
drivers/isdn/hardware/mISDN/mISDNinfineon.c
drivers/media/IR/Kconfig
drivers/media/dvb/dm1105/Kconfig
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/siano/Kconfig
drivers/media/dvb/ttpci/Kconfig
drivers/media/video/bt8xx/Kconfig
drivers/media/video/cx18/Kconfig
drivers/media/video/cx231xx/Kconfig
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx88/Kconfig
drivers/media/video/em28xx/Kconfig
drivers/media/video/ivtv/Kconfig
drivers/media/video/saa7134/Kconfig
drivers/media/video/tlg2300/Kconfig
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/v4l2-ctrls.c
drivers/net/caif/caif_spi_slave.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/phy/Kconfig
drivers/net/phy/phy.c
drivers/net/qlcnic/qlcnic_main.c
drivers/net/usb/usbnet.c
drivers/net/wan/farsync.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/p54/p54pci.c
drivers/s390/block/dasd.c
drivers/s390/net/claw.c
drivers/s390/net/claw.h
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/ctcm_main.h
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/ctcm_sysfs.c
drivers/watchdog/Kconfig
drivers/watchdog/hpwdt.c
fs/afs/cell.c
fs/afs/dir.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/mntpt.c
fs/afs/proc.c
fs/afs/super.c
fs/bad_inode.c
fs/cifs/README
fs/compat.c
fs/compat_ioctl.c
fs/ioctl.c
fs/logfs/dir.c
fs/logfs/file.c
fs/logfs/logfs.h
fs/nfs/Kconfig
fs/nfs/dns_resolve.c
fs/nfs/dns_resolve.h
fs/ocfs2/acl.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/refcounttree.c
fs/partitions/ibm.c
fs/proc/inode.c
fs/stat.c
fs/utimes.c
include/linux/compat.h
include/linux/dma-mapping.h
include/linux/etherdevice.h
include/linux/fs.h
include/linux/netpoll.h
include/linux/syscalls.h
include/linux/time.h
include/net/bluetooth/l2cap.h
include/net/sock.h
kernel/time/timekeeping.c
mm/memory.c
mm/nommu.c
net/bluetooth/l2cap.c
net/caif/cfpkt_skbuff.c
net/can/bcm.c
net/dns_resolver/dns_key.c
net/dns_resolver/dns_query.c
net/dsa/Kconfig
net/sched/sch_api.c
net/sched/sch_atm.c
net/sched/sch_sfq.c
net/sched/sch_tbf.c
net/sched/sch_teql.c
net/wireless/mlme.c
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/expr.c
scripts/kconfig/lkc.h
scripts/kconfig/nconf.c
scripts/setlocalversion
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-report.c
tools/perf/builtin-timechart.c
tools/perf/builtin-trace.c
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/include/linux/list.h
tools/perf/util/include/linux/types.h
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/pstack.h
tools/perf/util/sort.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/ui/browser.c [new file with mode: 0644]
tools/perf/util/ui/browser.h [new file with mode: 0644]
tools/perf/util/ui/browsers/annotate.c [new file with mode: 0644]
tools/perf/util/ui/browsers/hists.c [moved from tools/perf/util/newt.c with 56% similarity]
tools/perf/util/ui/browsers/map.c [new file with mode: 0644]
tools/perf/util/ui/browsers/map.h [new file with mode: 0644]
tools/perf/util/ui/helpline.c [new file with mode: 0644]
tools/perf/util/ui/helpline.h [new file with mode: 0644]
tools/perf/util/ui/libslang.h [new file with mode: 0644]
tools/perf/util/ui/progress.c [new file with mode: 0644]
tools/perf/util/ui/progress.h [new file with mode: 0644]
tools/perf/util/ui/setup.c [new file with mode: 0644]
tools/perf/util/ui/util.c [new file with mode: 0644]
tools/perf/util/ui/util.h [new file with mode: 0644]

index bbcc15651a21c1e1dac6c390d0fc17e93dda66be..2db4283efa8dbf99e0e6576edc8d0a054d3b299d 100644 (file)
@@ -374,8 +374,6 @@ prototypes:
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
-       int (*ioctl) (struct inode *, struct file *, unsigned int,
-                       unsigned long);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
@@ -409,8 +407,7 @@ write:                      no
 aio_write:             no
 readdir:               no
 poll:                  no
-ioctl:                 yes     (see below)
-unlocked_ioctl:                no      (see below)
+unlocked_ioctl:                no
 compat_ioctl:          no
 mmap:                  no
 open:                  no
@@ -453,9 +450,6 @@ move ->readdir() to inode_operations and use a separate method for directory
 anything that resembles union-mount we won't have a struct file for all
 components. And there are other reasons why the current interface is a mess...
 
-->ioctl() on regular files is superceded by the ->unlocked_ioctl() that
-doesn't take the BKL.
-
 ->read on directories probably must go away - we should just enforce -EISDIR
 in sys_read() and friends.
 
index 94677e7dcb1311ac504c7f171fd6139deecddb5a..ed7e5efc06d8fe33dc54a2122a059fdbec874092 100644 (file)
@@ -727,7 +727,6 @@ struct file_operations {
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
-       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
@@ -768,10 +767,7 @@ otherwise noted.
        activity on this file and (optionally) go to sleep until there
        is activity. Called by the select(2) and poll(2) system calls
 
-  ioctl: called by the ioctl(2) system call
-
-  unlocked_ioctl: called by the ioctl(2) system call. Filesystems that do not
-       require the BKL should use this method instead of the ioctl() above.
+  unlocked_ioctl: called by the ioctl(2) system call.
 
   compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
         are used on 64 bit kernels.
index 7431c283f15b3efaed73050a0c33d721a9fc8a57..788111d215596a6d718c1aa215fe4c3a6f011d26 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -189,7 +189,6 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 export KBUILD_BUILDHOST := $(SUBARCH)
 ARCH           ?= $(SUBARCH)
-CROSS_COMPILE  ?=
 CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)
 
 # Architecture as present in compile.h
index 88131c6e42e3fe7f4ed84b451ee7247c120ae24b..fb58150a7e8f4fb667f10ac7ae0a772b021f9b53 100644 (file)
@@ -244,7 +244,7 @@ do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
        return error;   
 }
 
-SYSCALL_DEFINE3(osf_statfs, char __user *, pathname,
+SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
                struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
        struct path path;
@@ -358,7 +358,7 @@ osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
        return do_mount("", dirname, "proc", flags, NULL);
 }
 
-SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
+SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
                int, flag, void __user *, data)
 {
        int retval;
@@ -932,7 +932,7 @@ SYSCALL_DEFINE3(osf_setitimer, int, which, struct itimerval32 __user *, in,
 
 }
 
-SYSCALL_DEFINE2(osf_utimes, char __user *, filename,
+SYSCALL_DEFINE2(osf_utimes, const char __user *, filename,
                struct timeval32 __user *, tvs)
 {
        struct timespec tv[2];
index 395a464353b8e48ac4e18ecb725fc0a960809898..88e608aebc8ccb61351d7be3b83364e4e590fe31 100644 (file)
@@ -387,7 +387,7 @@ EXPORT_SYMBOL(dump_elf_task_fp);
  * sys_execve() executes a new program.
  */
 asmlinkage int
-do_sys_execve(char __user *ufilename, char __user * __user *argv,
+do_sys_execve(const char __user *ufilename, char __user * __user *argv,
              char __user * __user *envp, struct pt_regs *regs)
 {
        int error;
index c23501842b98b06465d94071209e6fcc819a651c..5b7c541a4c63d0dc6ae9405f70470f1f4c2108c4 100644 (file)
@@ -62,7 +62,7 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
 /* sys_execve() executes a new program.
  * This is called indirectly via a small wrapper
  */
-asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv,
+asmlinkage int sys_execve(const char __user *filenamei, char __user * __user *argv,
                          char __user * __user *envp, struct pt_regs *regs)
 {
        int error;
@@ -84,7 +84,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
        int ret;
 
        memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve((char *)filename, (char __user * __user *)argv,
+       ret = do_execve(filename, (char __user * __user *)argv,
                        (char __user * __user *)envp, &regs);
        if (ret < 0)
                goto out;
index 33ff678e32f2ef0e55a80e85a77d5b236e1b41c0..4ad8da15ef2b3972f4412631ceb1a5cf1d63eba2 100644 (file)
@@ -141,7 +141,7 @@ static long cp_oldabi_stat64(struct kstat *stat,
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-asmlinkage long sys_oabi_stat64(char __user * filename,
+asmlinkage long sys_oabi_stat64(const char __user * filename,
                                struct oldabi_stat64 __user * statbuf)
 {
        struct kstat stat;
@@ -151,7 +151,7 @@ asmlinkage long sys_oabi_stat64(char __user * filename,
        return error;
 }
 
-asmlinkage long sys_oabi_lstat64(char __user * filename,
+asmlinkage long sys_oabi_lstat64(const char __user * filename,
                                 struct oldabi_stat64 __user * statbuf)
 {
        struct kstat stat;
@@ -172,7 +172,7 @@ asmlinkage long sys_oabi_fstat64(unsigned long fd,
 }
 
 asmlinkage long sys_oabi_fstatat64(int dfd,
-                                  char __user *filename,
+                                  const char __user *filename,
                                   struct oldabi_stat64  __user *statbuf,
                                   int flag)
 {
index 66a197266637e07f898102903e609ae710f521f8..ab608b70b24d532651649dfbe0dc7e6750d7c51c 100644 (file)
@@ -21,7 +21,7 @@ asmlinkage int sys_clone(unsigned long, unsigned long,
                         unsigned long, unsigned long,
                         struct pt_regs *);
 asmlinkage int sys_vfork(struct pt_regs *);
-asmlinkage int sys_execve(char __user *, char __user *__user *,
+asmlinkage int sys_execve(const char __user *, char __user *__user *,
                          char __user *__user *, struct pt_regs *);
 
 /* kernel/signal.c */
index 2d76515745a4f0edf28f7a09a53cfca093da4bda..e5daddff397dd166e9ba16b089f2cdc2daf022fb 100644 (file)
@@ -383,7 +383,8 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
                       0, NULL, NULL);
 }
 
-asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv,
+asmlinkage int sys_execve(const char __user *ufilename,
+                         char __user *__user *uargv,
                          char __user *__user *uenvp, struct pt_regs *regs)
 {
        int error;
index 93ec07da2e513866356aba2baedaa0739e1351f2..a566f61c002aecaec8caa8f8ccca6a2f318ca7fa 100644 (file)
@@ -209,7 +209,7 @@ copy_thread(unsigned long clone_flags,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
+asmlinkage int sys_execve(const char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
        int error;
        char *filename;
index 21d0fd19276dffef3a87e888cd213aca9a688469..428931cf2f0c44adc9d6092bff72cca6c596c54a 100644 (file)
@@ -250,7 +250,8 @@ int copy_thread(unsigned long clone_flags,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
+asmlinkage int sys_execve(const char __user *name, char __user * __user *argv,
+                         char __user * __user *envp)
 {
        int error;
        char * filename;
index 8c8b0ffa6ad709d9a9d32b95ff380a3a734f84f0..8b7b78d77d5c46ba3b9d31bf1933cf504c7f377a 100644 (file)
@@ -212,7 +212,7 @@ int copy_thread(unsigned long clone_flags,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...)
+asmlinkage int sys_execve(const char *name, char **argv, char **envp,int dummy,...)
 {
        int error;
        char * filename;
index bb8b0fff32b3f5c46f9d348f98ebe9a0b2f177ec..46f36fc5125fbdc2a465692a5766e3a37fb9d632 100644 (file)
@@ -353,7 +353,7 @@ asmlinkage unsigned long sys_mmap2(
                                int fd, long pgoff);
 struct pt_regs;
 struct sigaction;
-long sys_execve(char __user *filename, char __user * __user *argv,
+long sys_execve(const char __user *filename, char __user * __user *argv,
                           char __user * __user *envp, struct pt_regs *regs);
 asmlinkage long sys_ia64_pipe(void);
 asmlinkage long sys_rt_sigaction(int sig,
index 53f1648c8b813cf496abf851830a0ce21f3aa333..a879c03b7f1cc0f97309c2cfff3ccb8b8a118385 100644 (file)
@@ -633,7 +633,7 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
 }
 
 long
-sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
+sys_execve (const char __user *filename, char __user * __user *argv, char __user * __user *envp,
            struct pt_regs *regs)
 {
        char *fname;
index bc8c8c1511b2eb23c07d6ad82c812d62841b5d94..8665a4d868ecb6f48506c6c354b9813be3f92b69 100644 (file)
@@ -288,7 +288,8 @@ asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+asmlinkage int sys_execve(const char __user *ufilename,
+                         char __user * __user *uargv,
                          char __user * __user *uenvp,
                          unsigned long r3, unsigned long r4, unsigned long r5,
                          unsigned long r6, struct pt_regs regs)
index 1a6be27cf165a0cd60c210e72abcf727c981c462..221d0b71ce3934948a7e4c3581975bfe5b37c4d4 100644 (file)
@@ -315,7 +315,7 @@ EXPORT_SYMBOL(dump_fpu);
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
+asmlinkage int sys_execve(const char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
        int error;
        char * filename;
index 6aa66134b433cf6312703189ad240b004900a5e8..6350f68cd0262ba7f78c2a60f3fb76e574b2d857 100644 (file)
@@ -350,7 +350,7 @@ void dump(struct pt_regs *fp)
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
+asmlinkage int sys_execve(const char *name, char **argv, char **envp)
 {
        int error;
        char * filename;
index f4e00b7f12594877e86c780258e7d93d9bd35490..6abab6ebedbee2514d23ebe0cdfeeeec4fe3ad39 100644 (file)
@@ -47,7 +47,7 @@ asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs
        return do_fork(flags, stack, regs, 0, NULL, NULL);
 }
 
-asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv,
+asmlinkage long microblaze_execve(const char __user *filenamei, char __user *__user *argv,
                        char __user *__user *envp, struct pt_regs *regs)
 {
        int error;
index 58bab2ef257fae911623b6296879db2d9d427578..bddce0bca1950ea599fcc8c7d954841250f85e0f 100644 (file)
@@ -254,7 +254,7 @@ asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
        int error;
        char * filename;
 
-       filename = getname((char __user *) (long)regs.regs[4]);
+       filename = getname((const char __user *) (long)regs.regs[4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
index 82b817c7f7b63b2faca0af0e7c2ad3c671ee2b22..762eb325b949a9869dac416318ef277ced79ece0 100644 (file)
@@ -268,7 +268,7 @@ asmlinkage long sys_vfork(void)
                       0, NULL, NULL);
 }
 
-asmlinkage long sys_execve(char __user *name,
+asmlinkage long sys_execve(const char __user *name,
                           char __user * __user *argv,
                           char __user * __user *envp)
 {
index 6935123178ebec4a9cd9d3dd6628376f4b081b6b..1444875a761165334ff1f9916bc7c5c31dd6eb19 100644 (file)
@@ -36,7 +36,7 @@ int hpux_execve(struct pt_regs *regs)
        int error;
        char *filename;
 
-       filename = getname((char __user *) regs->gr[26]);
+       filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
@@ -169,7 +169,7 @@ static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf)
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-long hpux_stat64(char __user *filename, struct hpux_stat64 __user *statbuf)
+long hpux_stat64(const char __user *filename, struct hpux_stat64 __user *statbuf)
 {
        struct kstat stat;
        int error = vfs_stat(filename, &stat);
@@ -191,7 +191,8 @@ long hpux_fstat64(unsigned int fd, struct hpux_stat64 __user *statbuf)
        return error;
 }
 
-long hpux_lstat64(char __user *filename, struct hpux_stat64 __user *statbuf)
+long hpux_lstat64(const char __user *filename,
+                 struct hpux_stat64 __user *statbuf)
 {
        struct kstat stat;
        int error = vfs_lstat(filename, &stat);
index e78a5add7f15e4b2fac02d962f839772ffc8e9fc..feacfb7896863240eb5d447ea6c48b772c6906a9 100644 (file)
@@ -1027,7 +1027,7 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
        int error;
        char *filename;
 
-       filename = getname((char __user *) a0);
+       filename = getname((const char __user *) a0);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
index 19471a1cef1a23766107c0c60e1d0048e2efe0d7..20fd701a686adfeffc10e718c078f074eab92eaa 100644 (file)
@@ -546,7 +546,7 @@ compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_siz
        return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
 }
 
-compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
+compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count,
                              u32 reg6, u32 poshi, u32 poslo)
 {
        return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
index f02e89ce4df1096cc95deabacae29486734648c4..5da7c562a90b5dc557524ed1ae6f41bce7258bac 100644 (file)
@@ -85,9 +85,10 @@ static void appldata_get_net_sum_data(void *data)
 
        rcu_read_lock();
        for_each_netdev_rcu(&init_net, dev) {
+               const struct rtnl_link_stats64 *stats;
                struct rtnl_link_stats64 temp;
-               const struct net_device_stats *stats = dev_get_stats(dev, &temp);
 
+               stats = dev_get_stats(dev, &temp);
                rx_packets += stats->rx_packets;
                tx_packets += stats->tx_packets;
                rx_bytes   += stats->rx_bytes;
index 5f0075150a651d99457c9e048f967187c1c65c50..1049ef27c15e83bb30092efc67c3517433e2bfe4 100644 (file)
 #define        __NR_pwritev            329
 #define __NR_rt_tgsigqueueinfo 330
 #define __NR_perf_event_open   331
-#define NR_syscalls 332
+#define __NR_fanotify_init     332
+#define __NR_fanotify_mark     333
+#define __NR_prlimit64         334
+#define NR_syscalls 335
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 73b624ed9cd8ae612eef9521e8e708b458895bab..1e6449c79ab6de6de8d7c9f1de8ed1b8bdde66d5 100644 (file)
@@ -436,7 +436,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
  * sys32_execve() executes a new program after the asm stub has set
  * things up for us.  This should basically do what I want it to.
  */
-asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
                             compat_uptr_t __user *envp)
 {
        struct pt_regs *regs = task_pt_regs(current);
@@ -570,7 +570,7 @@ static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
        return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 
 }
 
-asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf)
+asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
 {
        struct kstat stat;
        int ret = vfs_stat(filename, &stat);
@@ -579,7 +579,7 @@ asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user
        return ret;
 }
 
-asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf)
+asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
 {
        struct kstat stat;
        int ret = vfs_lstat(filename, &stat);
@@ -597,7 +597,7 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * sta
        return ret;
 }
 
-asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename,
+asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename,
                                struct stat64_emu31 __user* statbuf, int flag)
 {
        struct kstat stat;
@@ -655,7 +655,7 @@ asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
        return sys_read(fd, buf, count);
 }
 
-asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
+asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count)
 {
        if ((compat_ssize_t) count < 0)
                return -EINVAL; 
index cb97afc85c94a93cbb7b6aac57351b98080ce78e..9635d759c2b9fbb107e39f326ff7b638bc353c36 100644 (file)
@@ -193,7 +193,7 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
                          compat_sigset_t __user *oset, size_t sigsetsize);
 long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
 long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
-long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
                  compat_uptr_t __user *envp);
 long sys32_init_module(void __user *umod, unsigned long len,
                       const char __user *uargs);
@@ -207,16 +207,16 @@ long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
                    size_t count);
 long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
                      s32 count);
-long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
-long sys32_lstat64(char __user * filename,
+long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf);
+long sys32_lstat64(const char __user * filename,
                   struct stat64_emu31 __user * statbuf);
 long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf);
-long sys32_fstatat64(unsigned int dfd, char __user *filename,
+long sys32_fstatat64(unsigned int dfd, const char __user *filename,
                     struct stat64_emu31 __user* statbuf, int flag);
 unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg);
 long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg);
 long sys32_read(unsigned int fd, char __user * buf, size_t count);
-long sys32_write(unsigned int fd, char __user * buf, size_t count);
+long sys32_write(unsigned int fd, const char __user * buf, size_t count);
 long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise);
 long sys32_fadvise64_64(struct fadvise64_64_args __user *args);
 long sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
index 672ce52341b451c1dc22ecf27629f7026197c86d..8e60fb23b90da9d61587c72938b785881683de93 100644 (file)
@@ -614,7 +614,7 @@ sys32_sysfs_wrapper:
 
        .globl  sys32_personality_wrapper
 sys32_personality_wrapper:
-       llgfr   %r2,%r2                 # unsigned long
+       llgfr   %r2,%r2                 # unsigned int
        jg      sys_s390_personality    # branch to system call
 
        .globl  sys32_setfsuid16_wrapper
@@ -1853,3 +1853,27 @@ sys32_execve_wrapper:
        llgtr   %r3,%r3                 # compat_uptr_t *
        llgtr   %r4,%r4                 # compat_uptr_t *
        jg      sys32_execve            # branch to system call
+
+       .globl  sys_fanotify_init_wrapper
+sys_fanotify_init_wrapper:
+       llgfr   %r2,%r2                 # unsigned int
+       llgfr   %r3,%r3                 # unsigned int
+       jg      sys_fanotify_init       # branch to system call
+
+       .globl  sys_fanotify_mark_wrapper
+sys_fanotify_mark_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgfr   %r3,%r3                 # unsigned int
+       sllg    %r4,%r4,32              # get high word of 64bit mask
+       lr      %r4,%r5                 # get low word of 64bit mask
+       llgfr   %r5,%r6                 # unsigned int
+       llgt    %r6,164(%r15)           # char *
+       jg      sys_fanotify_mark       # branch to system call
+
+       .globl  sys_prlimit64_wrapper
+sys_prlimit64_wrapper:
+       lgfr    %r2,%r2                 # pid_t
+       llgfr   %r3,%r3                 # unsigned int
+       llgtr   %r4,%r4                 # const struct rlimit64 __user *
+       llgtr   %r5,%r5                 # struct rlimit64 __user *
+       jg      sys_prlimit64           # branch to system call
index eb15c12ec158c329146ded2d797cb907a186d4a5..403fb430a896104b0c5f7982a9dd76ecf80d5e95 100644 (file)
@@ -31,7 +31,7 @@ struct old_sigaction;
 long sys_mmap2(struct s390_mmap_arg_struct __user  *arg);
 long sys_s390_ipc(uint call, int first, unsigned long second,
             unsigned long third, void __user *ptr);
-long sys_s390_personality(unsigned long personality);
+long sys_s390_personality(unsigned int personality);
 long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
                    size_t len, int advice);
 long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args);
@@ -42,7 +42,7 @@ long sys_clone(unsigned long newsp, unsigned long clone_flags,
               int __user *parent_tidptr, int __user *child_tidptr);
 long sys_vfork(void);
 void execve_tail(void);
-long sys_execve(char __user *name, char __user * __user *argv,
+long sys_execve(const char __user *name, char __user * __user *argv,
                char __user * __user *envp);
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
index 1039fdea15b58bdb805f92838c9342d95253c4fb..7eafaf2662b92fca4aff3f36ea980148695cb24a 100644 (file)
@@ -267,7 +267,7 @@ asmlinkage void execve_tail(void)
 /*
  * sys_execve() executes a new program.
  */
-SYSCALL_DEFINE3(execve, char __user *, name, char __user * __user *, argv,
+SYSCALL_DEFINE3(execve, const char __user *, name, char __user * __user *, argv,
                char __user * __user *, envp)
 {
        struct pt_regs *regs = task_pt_regs(current);
index 7b6b0f81a28308cf9f72c43126307c035cc83bf4..476081440df9f4ec7674a0aed3f8dbbadcfd6fe5 100644 (file)
@@ -131,9 +131,9 @@ SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
 }
 
 #ifdef CONFIG_64BIT
-SYSCALL_DEFINE1(s390_personality, unsigned long, personality)
+SYSCALL_DEFINE1(s390_personality, unsigned int, personality)
 {
-       int ret;
+       unsigned int ret;
 
        if (current->personality == PER_LINUX32 && personality == PER_LINUX)
                personality = PER_LINUX32;
index 201ce6bed34ec2587fd4bf04d80bfd0de351e5e1..a8fee1b14395a1472a5d8fa2f34f1ed34eafb4c8 100644 (file)
@@ -340,3 +340,6 @@ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
+SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
+SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper)
+SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper)
index 8b30200305c34911be0727f1b434e21f8e4e7b65..be201fdc97aa79bbf5470c8a582e20ecb7e78991 100644 (file)
@@ -19,7 +19,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs __regs);
-asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+asmlinkage int sys_execve(const char __user *ufilename, char __user * __user *uargv,
                          char __user * __user *uenvp, unsigned long r7,
                          struct pt_regs __regs);
 asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
index 751fd88113649cbc120ab539cad69c3ff23e7ac2..ee519f41d9500561b75c31caf0b293557e1d7e76 100644 (file)
@@ -21,7 +21,7 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
                         unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs *pregs);
-asmlinkage int sys_execve(char *ufilename, char **uargv,
+asmlinkage int sys_execve(const char *ufilename, char **uargv,
                          char **uenvp, unsigned long r5,
                          unsigned long r6, unsigned long r7,
                          struct pt_regs *pregs);
index d4ca6480e355bebce7ccd9a628817cb37f825e84..68d128d651b32cb7df96249260d73e6e49012c42 100644 (file)
@@ -483,7 +483,7 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *ufilename, char **uargv,
+asmlinkage int sys_execve(const char *ufilename, char **uargv,
                          char **uenvp, unsigned long r5,
                          unsigned long r6, unsigned long r7,
                          struct pt_regs *pregs)
index c0ca87553e1c22e34c7aa11669795e0e74c34965..e6375a750d9a641f4b253fdf2894fa989973b347 100644 (file)
@@ -162,7 +162,7 @@ static int cp_compat_stat64(struct kstat *stat,
        return err;
 }
 
-asmlinkage long compat_sys_stat64(char __user * filename,
+asmlinkage long compat_sys_stat64(const char __user * filename,
                struct compat_stat64 __user *statbuf)
 {
        struct kstat stat;
@@ -173,7 +173,7 @@ asmlinkage long compat_sys_stat64(char __user * filename,
        return error;
 }
 
-asmlinkage long compat_sys_lstat64(char __user * filename,
+asmlinkage long compat_sys_lstat64(const char __user * filename,
                struct compat_stat64 __user *statbuf)
 {
        struct kstat stat;
@@ -195,7 +195,8 @@ asmlinkage long compat_sys_fstat64(unsigned int fd,
        return error;
 }
 
-asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
+asmlinkage long compat_sys_fstatat64(unsigned int dfd,
+               const char __user *filename,
                struct compat_stat64 __user * statbuf, int flag)
 {
        struct kstat stat;
index 97974c1bdd126b8c92ab5023aa3806e3115be4dc..59b20d93b6d43b80047bc4012089e2b8d31c1708 100644 (file)
@@ -44,7 +44,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
        PT_REGS_SP(regs) = esp;
 }
 
-static long execve1(char *file, char __user * __user *argv,
+static long execve1(const char *file, char __user * __user *argv,
                    char __user *__user *env)
 {
        long error;
@@ -61,7 +61,7 @@ static long execve1(char *file, char __user * __user *argv,
        return error;
 }
 
-long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
+long um_execve(const char *file, char __user *__user *argv, char __user *__user *env)
 {
        long err;
 
@@ -71,7 +71,7 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
        return err;
 }
 
-long sys_execve(char __user *file, char __user *__user *argv,
+long sys_execve(const char __user *file, char __user *__user *argv,
                char __user *__user *env)
 {
        long error;
index 3bda43c7a7863e5461ee711e2fcbdaaff3efa387..1303a105fe91dc5aabca314e4e94faf8573b9c65 100644 (file)
@@ -1 +1 @@
-extern long um_execve(char *file, char __user *__user *argv, char __user *__user *env);
+extern long um_execve(const char *file, char __user *__user *argv, char __user *__user *env);
index 4393173923f5f408019456a3428d9d7d1c1f75e5..7427c0b1930cbb18879ccfb047b90391bb322e39 100644 (file)
@@ -58,7 +58,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 
        fs = get_fs();
        set_fs(KERNEL_DS);
-       ret = um_execve((char *)filename, (char __user *__user *)argv,
+       ret = um_execve(filename, (char __user *__user *)argv,
                        (char __user *__user *) envp);
        set_fs(fs);
 
index 3d093311d5e230cd9defbabc80e1ea5398a2e614..849813f398e75e8f699b5a5e999efad7df1a76a8 100644 (file)
@@ -51,7 +51,7 @@
 #define AA(__x)                ((unsigned long)(__x))
 
 
-asmlinkage long sys32_truncate64(char __user *filename,
+asmlinkage long sys32_truncate64(const char __user *filename,
                                 unsigned long offset_low,
                                 unsigned long offset_high)
 {
@@ -96,7 +96,7 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
        return 0;
 }
 
-asmlinkage long sys32_stat64(char __user *filename,
+asmlinkage long sys32_stat64(const char __user *filename,
                             struct stat64 __user *statbuf)
 {
        struct kstat stat;
@@ -107,7 +107,7 @@ asmlinkage long sys32_stat64(char __user *filename,
        return ret;
 }
 
-asmlinkage long sys32_lstat64(char __user *filename,
+asmlinkage long sys32_lstat64(const char __user *filename,
                              struct stat64 __user *statbuf)
 {
        struct kstat stat;
@@ -126,7 +126,7 @@ asmlinkage long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
        return ret;
 }
 
-asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename,
+asmlinkage long sys32_fstatat(unsigned int dfd, const char __user *filename,
                              struct stat64 __user *statbuf, int flag)
 {
        struct kstat stat;
@@ -408,8 +408,8 @@ asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count,
                         ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
-asmlinkage long sys32_pwrite(unsigned int fd, char __user *ubuf, u32 count,
-                            u32 poslo, u32 poshi)
+asmlinkage long sys32_pwrite(unsigned int fd, const char __user *ubuf,
+                            u32 count, u32 poslo, u32 poshi)
 {
        return sys_pwrite64(fd, ubuf, count,
                          ((loff_t)AA(poshi) << 32) | AA(poslo));
@@ -449,7 +449,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd,
        return ret;
 }
 
-asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
                             compat_uptr_t __user *envp, struct pt_regs *regs)
 {
        long error;
index 625c3f0e741aab7bd75d839cadf7084c303baa61..8ca82839288a35e326f43fbac24a8384eb497652 100644 (file)
@@ -37,6 +37,13 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
 #define __pa_nodebug(x)        __phys_addr_nodebug((unsigned long)(x))
 /* __pa_symbol should be used for C visible symbols.
    This seems to be the official gcc blessed way to do such arithmetic. */
+/*
+ * We need __phys_reloc_hide() here because gcc may assume that there is no
+ * overflow during __pa() calculation and can optimize it unexpectedly.
+ * Newer versions of gcc provide -fno-strict-overflow switch to handle this
+ * case properly. Once all supported versions of gcc understand it, we can
+ * remove this Voodoo magic stuff. (i.e. once gcc3.x is deprecated)
+ */
 #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x)))
 
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
index cf4e2e381cbab6848e324783e476781ed8555b7f..cb238526a9f12959ebed76a6d76d0d9e750a17bd 100644 (file)
 #include <asm/ia32.h>
 
 /* ia32/sys_ia32.c */
-asmlinkage long sys32_truncate64(char __user *, unsigned long, unsigned long);
+asmlinkage long sys32_truncate64(const char __user *, unsigned long, unsigned long);
 asmlinkage long sys32_ftruncate64(unsigned int, unsigned long, unsigned long);
 
-asmlinkage long sys32_stat64(char __user *, struct stat64 __user *);
-asmlinkage long sys32_lstat64(char __user *, struct stat64 __user *);
+asmlinkage long sys32_stat64(const char __user *, struct stat64 __user *);
+asmlinkage long sys32_lstat64(const char __user *, struct stat64 __user *);
 asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *);
-asmlinkage long sys32_fstatat(unsigned int, char __user *,
+asmlinkage long sys32_fstatat(unsigned int, const char __user *,
                              struct stat64 __user *, int);
 struct mmap_arg_struct32;
 asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *);
@@ -49,12 +49,12 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t);
 asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *);
 
 asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
-asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);
+asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32);
 
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *,
+asmlinkage long sys32_execve(const char __user *, compat_uptr_t __user *,
                             compat_uptr_t __user *, struct pt_regs *);
 asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
 
index 5c044b43e9a7359ce834b54e5b6f8d736d95e5cc..feb2ff9bfc2d178855b19fb8cf4a26e506e3317a 100644 (file)
@@ -23,7 +23,7 @@ long sys_iopl(unsigned int, struct pt_regs *);
 /* kernel/process.c */
 int sys_fork(struct pt_regs *);
 int sys_vfork(struct pt_regs *);
-long sys_execve(char __user *, char __user * __user *,
+long sys_execve(const char __user *, char __user * __user *,
                char __user * __user *, struct pt_regs *);
 long sys_clone(unsigned long, unsigned long, void __user *,
               void __user *, struct pt_regs *);
index aa558ac0306e5859bc41863861cc5a1620cf0c1e..42d412fd8b02cdd369b5cc8db5a67aa5cc7a0770 100644 (file)
@@ -34,6 +34,7 @@
  */
 
 #define UV_ITEMS_PER_DESCRIPTOR                8
+/* the 'throttle' to prevent the hardware stay-busy bug */
 #define MAX_BAU_CONCURRENT             3
 #define UV_CPUS_PER_ACT_STATUS         32
 #define UV_ACT_STATUS_MASK             0x3
 #define UV_DESC_BASE_PNODE_SHIFT       49
 #define UV_PAYLOADQ_PNODE_SHIFT                49
 #define UV_PTC_BASENAME                        "sgi_uv/ptc_statistics"
+#define UV_BAU_BASENAME                        "sgi_uv/bau_tunables"
+#define UV_BAU_TUNABLES_DIR            "sgi_uv"
+#define UV_BAU_TUNABLES_FILE           "bau_tunables"
+#define WHITESPACE                     " \t\n"
 #define uv_physnodeaddr(x)             ((__pa((unsigned long)(x)) & uv_mmask))
 #define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
 #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
-#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x0000000009UL
+/* [19:16] SOFT_ACK timeout period  19: 1 is urgency 7  17:16 1 is multiplier */
+#define BAU_MISC_CONTROL_MULT_MASK 3
+
+#define UVH_AGING_PRESCALE_SEL 0x000000b000UL
+/* [30:28] URGENCY_7  an index into a table of times */
+#define BAU_URGENCY_7_SHIFT 28
+#define BAU_URGENCY_7_MASK 7
+
+#define UVH_TRANSACTION_TIMEOUT 0x000000b200UL
+/* [45:40] BAU - BAU transaction timeout select - a multiplier */
+#define BAU_TRANS_SHIFT 40
+#define BAU_TRANS_MASK 0x3f
 
 /*
  * bits in UVH_LB_BAU_SB_ACTIVATION_STATUS_0/1
 #define DESC_STATUS_SOURCE_TIMEOUT     3
 
 /*
- * source side threshholds at which message retries print a warning
- */
-#define SOURCE_TIMEOUT_LIMIT           20
-#define DESTINATION_TIMEOUT_LIMIT      20
-
-/*
- * misc. delays, in microseconds
+ * delay for 'plugged' timeout retries, in microseconds
  */
-#define THROTTLE_DELAY                 10
-#define TIMEOUT_DELAY                  10
-#define BIOS_TO                                1000
-/* BIOS is assumed to set the destination timeout to 1003520 nanoseconds */
+#define PLUGGED_DELAY                  10
 
 /*
  * threshholds at which to use IPI to free resources
  */
+/* after this # consecutive 'plugged' timeouts, use IPI to release resources */
 #define PLUGSB4RESET 100
-#define TIMEOUTSB4RESET 100
+/* after this many consecutive timeouts, use IPI to release resources */
+#define TIMEOUTSB4RESET 1
+/* at this number uses of IPI to release resources, giveup the request */
+#define IPI_RESET_LIMIT 1
+/* after this # consecutive successes, bump up the throttle if it was lowered */
+#define COMPLETE_THRESHOLD 5
 
 /*
  * number of entries in the destination side payload queue
 #define FLUSH_GIVEUP                   3
 #define FLUSH_COMPLETE                 4
 
+/*
+ * tuning the action when the numalink network is extremely delayed
+ */
+#define CONGESTED_RESPONSE_US 1000 /* 'long' response time, in microseconds */
+#define CONGESTED_REPS 10 /* long delays averaged over this many broadcasts */
+#define CONGESTED_PERIOD 30 /* time for the bau to be disabled, in seconds */
+
 /*
  * Distribution: 32 bytes (256 bits) (bytes 0-0x1f of descriptor)
  * If the 'multilevel' flag in the header portion of the descriptor
@@ -300,37 +321,16 @@ struct bau_payload_queue_entry {
        /* bytes 24-31 */
 };
 
-/*
- * one per-cpu; to locate the software tables
- */
-struct bau_control {
-       struct bau_desc *descriptor_base;
+struct msg_desc {
+       struct bau_payload_queue_entry *msg;
+       int msg_slot;
+       int sw_ack_slot;
        struct bau_payload_queue_entry *va_queue_first;
        struct bau_payload_queue_entry *va_queue_last;
-       struct bau_payload_queue_entry *bau_msg_head;
-       struct bau_control *uvhub_master;
-       struct bau_control *socket_master;
-       unsigned long timeout_interval;
-       atomic_t active_descriptor_count;
-       int max_concurrent;
-       int max_concurrent_constant;
-       int retry_message_scans;
-       int plugged_tries;
-       int timeout_tries;
-       int ipi_attempts;
-       int conseccompletes;
-       short cpu;
-       short uvhub_cpu;
-       short uvhub;
-       short cpus_in_socket;
-       short cpus_in_uvhub;
-       unsigned short message_number;
-       unsigned short uvhub_quiesce;
-       short socket_acknowledge_count[DEST_Q_SIZE];
-       cycles_t send_message;
-       spinlock_t masks_lock;
-       spinlock_t uvhub_lock;
-       spinlock_t queue_lock;
+};
+
+struct reset_args {
+       int sender;
 };
 
 /*
@@ -344,18 +344,25 @@ struct ptc_stats {
        unsigned long s_dtimeout; /* destination side timeouts */
        unsigned long s_time; /* time spent in sending side */
        unsigned long s_retriesok; /* successful retries */
-       unsigned long s_ntargcpu; /* number of cpus targeted */
-       unsigned long s_ntarguvhub; /* number of uvhubs targeted */
-       unsigned long s_ntarguvhub16; /* number of times >= 16 target hubs */
-       unsigned long s_ntarguvhub8; /* number of times >= 8 target hubs */
-       unsigned long s_ntarguvhub4; /* number of times >= 4 target hubs */
-       unsigned long s_ntarguvhub2; /* number of times >= 2 target hubs */
-       unsigned long s_ntarguvhub1; /* number of times == 1 target hub */
+       unsigned long s_ntargcpu; /* total number of cpu's targeted */
+       unsigned long s_ntargself; /* times the sending cpu was targeted */
+       unsigned long s_ntarglocals; /* targets of cpus on the local blade */
+       unsigned long s_ntargremotes; /* targets of cpus on remote blades */
+       unsigned long s_ntarglocaluvhub; /* targets of the local hub */
+       unsigned long s_ntargremoteuvhub; /* remotes hubs targeted */
+       unsigned long s_ntarguvhub; /* total number of uvhubs targeted */
+       unsigned long s_ntarguvhub16; /* number of times target hubs >= 16*/
+       unsigned long s_ntarguvhub8; /* number of times target hubs >= 8 */
+       unsigned long s_ntarguvhub4; /* number of times target hubs >= 4 */
+       unsigned long s_ntarguvhub2; /* number of times target hubs >= 2 */
+       unsigned long s_ntarguvhub1; /* number of times target hubs == 1 */
        unsigned long s_resets_plug; /* ipi-style resets from plug state */
        unsigned long s_resets_timeout; /* ipi-style resets from timeouts */
        unsigned long s_busy; /* status stayed busy past s/w timer */
        unsigned long s_throttles; /* waits in throttle */
        unsigned long s_retry_messages; /* retry broadcasts */
+       unsigned long s_bau_reenabled; /* for bau enable/disable */
+       unsigned long s_bau_disabled; /* for bau enable/disable */
        /* destination statistics */
        unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */
        unsigned long d_onetlb; /* times just one tlb on this cpu was flushed */
@@ -370,6 +377,52 @@ struct ptc_stats {
        unsigned long d_rcanceled; /* number of messages canceled by resets */
 };
 
+/*
+ * one per-cpu; to locate the software tables
+ */
+struct bau_control {
+       struct bau_desc *descriptor_base;
+       struct bau_payload_queue_entry *va_queue_first;
+       struct bau_payload_queue_entry *va_queue_last;
+       struct bau_payload_queue_entry *bau_msg_head;
+       struct bau_control *uvhub_master;
+       struct bau_control *socket_master;
+       struct ptc_stats *statp;
+       unsigned long timeout_interval;
+       unsigned long set_bau_on_time;
+       atomic_t active_descriptor_count;
+       int plugged_tries;
+       int timeout_tries;
+       int ipi_attempts;
+       int conseccompletes;
+       int baudisabled;
+       int set_bau_off;
+       short cpu;
+       short uvhub_cpu;
+       short uvhub;
+       short cpus_in_socket;
+       short cpus_in_uvhub;
+       unsigned short message_number;
+       unsigned short uvhub_quiesce;
+       short socket_acknowledge_count[DEST_Q_SIZE];
+       cycles_t send_message;
+       spinlock_t uvhub_lock;
+       spinlock_t queue_lock;
+       /* tunables */
+       int max_bau_concurrent;
+       int max_bau_concurrent_constant;
+       int plugged_delay;
+       int plugsb4reset;
+       int timeoutsb4reset;
+       int ipi_reset_limit;
+       int complete_threshold;
+       int congested_response_us;
+       int congested_reps;
+       int congested_period;
+       cycles_t period_time;
+       long period_requests;
+};
+
 static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
 {
        return constant_test_bit(uvhub, &dstp->bits[0]);
index 980508c79082fadaacbc0339c0fe196d6a6dd5ce..e3b534cda49a8097dde55400083d7eeb8f9c694c 100644 (file)
@@ -1606,7 +1606,7 @@ void __init init_apic_mappings(void)
                 * acpi lapic path already maps that address in
                 * acpi_register_lapic_address()
                 */
-               if (!acpi_lapic)
+               if (!acpi_lapic && !smp_found_config)
                        set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
 
                apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
index 107711bf0ee8f9ff05e886b2143f1f69123d0d41..febb12cea795268f224a9d39937e3f27bb86bf67 100644 (file)
@@ -656,6 +656,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
        cpuc = &__get_cpu_var(cpu_hw_events);
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               int overflow;
 
                if (!test_bit(idx, cpuc->active_mask))
                        continue;
@@ -666,12 +667,14 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
                WARN_ON_ONCE(hwc->idx != idx);
 
                /* it might be unflagged overflow */
-               handled = p4_pmu_clear_cccr_ovf(hwc);
+               overflow = p4_pmu_clear_cccr_ovf(hwc);
 
                val = x86_perf_event_update(event);
-               if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
+               if (!overflow && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
                        continue;
 
+               handled += overflow;
+
                /* event overflow for sure */
                data.period = event->hw.last_period;
 
@@ -687,7 +690,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
                inc_irq_stat(apic_perf_irqs);
        }
 
-       return handled;
+       return handled > 0;
 }
 
 /*
index c5ea5cdbe7b3d86a927f82835147c42c6d93fabf..17be5ec7cbbad332973b6b46a79cdb3db2832f74 100644 (file)
@@ -1185,13 +1185,13 @@ END(kernel_thread_helper)
  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
  *
  * C extern interface:
- *      extern long execve(char *name, char **argv, char **envp)
+ *      extern long execve(const char *name, char **argv, char **envp)
  *
  * asm input arguments:
  *     rdi: name, rsi: argv, rdx: envp
  *
  * We want to fallback into:
- *     extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs)
+ *     extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
  *
  * do_sys_execve asm fallback arguments:
  *     rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
index d86dbf7e54be4384aae5c2c886e3e690780f40f3..d7b6f7fb4fecfd44205d63ab6cfebfb400e8b21a 100644 (file)
@@ -274,6 +274,18 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
 
 void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }
 
+static void __init smp_register_lapic_address(unsigned long address)
+{
+       mp_lapic_addr = address;
+
+       set_fixmap_nocache(FIX_APIC_BASE, address);
+       if (boot_cpu_physical_apicid == -1U) {
+               boot_cpu_physical_apicid  = read_apic_id();
+               apic_version[boot_cpu_physical_apicid] =
+                        GET_APIC_VERSION(apic_read(APIC_LVR));
+       }
+}
+
 static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
 {
        char str[16];
@@ -295,6 +307,10 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
        if (early)
                return 1;
 
+       /* Initialize the lapic mapping */
+       if (!acpi_lapic)
+               smp_register_lapic_address(mpc->lapic);
+
        if (mpc->oemptr)
                x86_init.mpparse.smp_read_mpc_oem(mpc);
 
index d401f1d2d06ef47c1dba0a33f86679a33ab24fa9..64ecaf0af9af4a88132994049570250809a585ea 100644 (file)
@@ -301,7 +301,7 @@ EXPORT_SYMBOL(kernel_thread);
 /*
  * sys_execve() executes a new program.
  */
-long sys_execve(char __user *name, char __user * __user *argv,
+long sys_execve(const char __user *name, char __user * __user *argv,
                char __user * __user *envp, struct pt_regs *regs)
 {
        long error;
index 7fea555929e24f2f411ea019b426e64c05ac2df0..59efb5390b37bec6d0de735c93483c35ba0ca43a 100644 (file)
@@ -8,6 +8,7 @@
  */
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
+#include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 
 #include <asm/irq_vectors.h>
 #include <asm/timer.h>
 
-struct msg_desc {
-       struct bau_payload_queue_entry *msg;
-       int msg_slot;
-       int sw_ack_slot;
-       struct bau_payload_queue_entry *va_queue_first;
-       struct bau_payload_queue_entry *va_queue_last;
+/* timeouts in nanoseconds (indexed by UVH_AGING_PRESCALE_SEL urgency7 30:28) */
+static int timeout_base_ns[] = {
+               20,
+               160,
+               1280,
+               10240,
+               81920,
+               655360,
+               5242880,
+               167772160
 };
-
-#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD        0x000000000bUL
-
-static int uv_bau_max_concurrent __read_mostly;
-
+static int timeout_us;
 static int nobau;
+static int baudisabled;
+static spinlock_t disable_lock;
+static cycles_t congested_cycles;
+
+/* tunables: */
+static int max_bau_concurrent = MAX_BAU_CONCURRENT;
+static int max_bau_concurrent_constant = MAX_BAU_CONCURRENT;
+static int plugged_delay = PLUGGED_DELAY;
+static int plugsb4reset = PLUGSB4RESET;
+static int timeoutsb4reset = TIMEOUTSB4RESET;
+static int ipi_reset_limit = IPI_RESET_LIMIT;
+static int complete_threshold = COMPLETE_THRESHOLD;
+static int congested_response_us = CONGESTED_RESPONSE_US;
+static int congested_reps = CONGESTED_REPS;
+static int congested_period = CONGESTED_PERIOD;
+static struct dentry *tunables_dir;
+static struct dentry *tunables_file;
+
 static int __init setup_nobau(char *arg)
 {
        nobau = 1;
@@ -52,10 +71,6 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
 static DEFINE_PER_CPU(struct bau_control, bau_control);
 static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
 
-struct reset_args {
-       int sender;
-};
-
 /*
  * Determine the first node on a uvhub. 'Nodes' are used for kernel
  * memory allocation.
@@ -126,7 +141,7 @@ static inline void uv_bau_process_retry_msg(struct msg_desc *mdp,
        struct ptc_stats *stat;
 
        msg = mdp->msg;
-       stat = &per_cpu(ptcstats, bcp->cpu);
+       stat = bcp->statp;
        stat->d_retries++;
        /*
         * cancel any message from msg+1 to the retry itself
@@ -146,15 +161,14 @@ static inline void uv_bau_process_retry_msg(struct msg_desc *mdp,
                        slot2 = msg2 - mdp->va_queue_first;
                        mmr = uv_read_local_mmr
                                (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
-                       msg_res = ((msg2->sw_ack_vector << 8) |
-                                  msg2->sw_ack_vector);
+                       msg_res = msg2->sw_ack_vector;
                        /*
                         * This is a message retry; clear the resources held
                         * by the previous message only if they timed out.
                         * If it has not timed out we have an unexpected
                         * situation to report.
                         */
-                       if (mmr & (msg_res << 8)) {
+                       if (mmr & (msg_res << UV_SW_ACK_NPENDING)) {
                                /*
                                 * is the resource timed out?
                                 * make everyone ignore the cancelled message.
@@ -164,9 +178,9 @@ static inline void uv_bau_process_retry_msg(struct msg_desc *mdp,
                                cancel_count++;
                                uv_write_local_mmr(
                                    UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS,
-                                       (msg_res << 8) | msg_res);
-                       } else
-                               printk(KERN_INFO "note bau retry: no effect\n");
+                                       (msg_res << UV_SW_ACK_NPENDING) |
+                                        msg_res);
+                       }
                }
        }
        if (!cancel_count)
@@ -190,7 +204,7 @@ static void uv_bau_process_message(struct msg_desc *mdp,
         * This must be a normal message, or retry of a normal message
         */
        msg = mdp->msg;
-       stat = &per_cpu(ptcstats, bcp->cpu);
+       stat = bcp->statp;
        if (msg->address == TLB_FLUSH_ALL) {
                local_flush_tlb();
                stat->d_alltlb++;
@@ -274,7 +288,7 @@ uv_do_reset(void *ptr)
 
        bcp = &per_cpu(bau_control, smp_processor_id());
        rap = (struct reset_args *)ptr;
-       stat = &per_cpu(ptcstats, bcp->cpu);
+       stat = bcp->statp;
        stat->d_resets++;
 
        /*
@@ -302,13 +316,13 @@ uv_do_reset(void *ptr)
                         */
                        mmr = uv_read_local_mmr
                                        (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
-                       msg_res = ((msg->sw_ack_vector << 8) |
-                                                  msg->sw_ack_vector);
+                       msg_res = msg->sw_ack_vector;
                        if (mmr & msg_res) {
                                stat->d_rcanceled++;
                                uv_write_local_mmr(
                                    UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS,
-                                                       msg_res);
+                                       (msg_res << UV_SW_ACK_NPENDING) |
+                                        msg_res);
                        }
                }
        }
@@ -386,17 +400,12 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
        unsigned long mmr_offset, int right_shift, int this_cpu,
        struct bau_control *bcp, struct bau_control *smaster, long try)
 {
-       int relaxes = 0;
        unsigned long descriptor_status;
-       unsigned long mmr;
-       unsigned long mask;
        cycles_t ttime;
-       cycles_t timeout_time;
-       struct ptc_stats *stat = &per_cpu(ptcstats, this_cpu);
+       struct ptc_stats *stat = bcp->statp;
        struct bau_control *hmaster;
 
        hmaster = bcp->uvhub_master;
-       timeout_time = get_cycles() + bcp->timeout_interval;
 
        /* spin on the status MMR, waiting for it to go idle */
        while ((descriptor_status = (((unsigned long)
@@ -423,7 +432,8 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
                         * pending.  In that case hardware returns the
                         * ERROR that looks like a destination timeout.
                         */
-                       if (cycles_2_us(ttime - bcp->send_message) < BIOS_TO) {
+                       if (cycles_2_us(ttime - bcp->send_message) <
+                                                       timeout_us) {
                                bcp->conseccompletes = 0;
                                return FLUSH_RETRY_PLUGGED;
                        }
@@ -435,26 +445,6 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
                         * descriptor_status is still BUSY
                         */
                        cpu_relax();
-                       relaxes++;
-                       if (relaxes >= 10000) {
-                               relaxes = 0;
-                               if (get_cycles() > timeout_time) {
-                                       quiesce_local_uvhub(hmaster);
-
-                                       /* single-thread the register change */
-                                       spin_lock(&hmaster->masks_lock);
-                                       mmr = uv_read_local_mmr(mmr_offset);
-                                       mask = 0UL;
-                                       mask |= (3UL < right_shift);
-                                       mask = ~mask;
-                                       mmr &= mask;
-                                       uv_write_local_mmr(mmr_offset, mmr);
-                                       spin_unlock(&hmaster->masks_lock);
-                                       end_uvhub_quiesce(hmaster);
-                                       stat->s_busy++;
-                                       return FLUSH_GIVEUP;
-                               }
-                       }
                }
        }
        bcp->conseccompletes++;
@@ -494,56 +484,116 @@ static inline int atomic_inc_unless_ge(spinlock_t *lock, atomic_t *v, int u)
        return 1;
 }
 
+/*
+ * Our retries are blocked by all destination swack resources being
+ * in use, and a timeout is pending. In that case hardware immediately
+ * returns the ERROR that looks like a destination timeout.
+ */
+static void
+destination_plugged(struct bau_desc *bau_desc, struct bau_control *bcp,
+                       struct bau_control *hmaster, struct ptc_stats *stat)
+{
+       udelay(bcp->plugged_delay);
+       bcp->plugged_tries++;
+       if (bcp->plugged_tries >= bcp->plugsb4reset) {
+               bcp->plugged_tries = 0;
+               quiesce_local_uvhub(hmaster);
+               spin_lock(&hmaster->queue_lock);
+               uv_reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+               spin_unlock(&hmaster->queue_lock);
+               end_uvhub_quiesce(hmaster);
+               bcp->ipi_attempts++;
+               stat->s_resets_plug++;
+       }
+}
+
+static void
+destination_timeout(struct bau_desc *bau_desc, struct bau_control *bcp,
+                       struct bau_control *hmaster, struct ptc_stats *stat)
+{
+       hmaster->max_bau_concurrent = 1;
+       bcp->timeout_tries++;
+       if (bcp->timeout_tries >= bcp->timeoutsb4reset) {
+               bcp->timeout_tries = 0;
+               quiesce_local_uvhub(hmaster);
+               spin_lock(&hmaster->queue_lock);
+               uv_reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+               spin_unlock(&hmaster->queue_lock);
+               end_uvhub_quiesce(hmaster);
+               bcp->ipi_attempts++;
+               stat->s_resets_timeout++;
+       }
+}
+
+/*
+ * Completions are taking a very long time due to a congested numalink
+ * network.
+ */
+static void
+disable_for_congestion(struct bau_control *bcp, struct ptc_stats *stat)
+{
+       int tcpu;
+       struct bau_control *tbcp;
+
+       /* let only one cpu do this disabling */
+       spin_lock(&disable_lock);
+       if (!baudisabled && bcp->period_requests &&
+           ((bcp->period_time / bcp->period_requests) > congested_cycles)) {
+               /* it becomes this cpu's job to turn on the use of the
+                  BAU again */
+               baudisabled = 1;
+               bcp->set_bau_off = 1;
+               bcp->set_bau_on_time = get_cycles() +
+                       sec_2_cycles(bcp->congested_period);
+               stat->s_bau_disabled++;
+               for_each_present_cpu(tcpu) {
+                       tbcp = &per_cpu(bau_control, tcpu);
+                               tbcp->baudisabled = 1;
+               }
+       }
+       spin_unlock(&disable_lock);
+}
+
 /**
  * uv_flush_send_and_wait
  *
  * Send a broadcast and wait for it to complete.
  *
- * The flush_mask contains the cpus the broadcast is to be sent to, plus
+ * The flush_mask contains the cpus the broadcast is to be sent to including
  * cpus that are on the local uvhub.
  *
- * Returns NULL if all flushing represented in the mask was done. The mask
- * is zeroed.
- * Returns @flush_mask if some remote flushing remains to be done. The
- * mask will have some bits still set, representing any cpus on the local
- * uvhub (not current cpu) and any on remote uvhubs if the broadcast failed.
+ * Returns 0 if all flushing represented in the mask was done.
+ * Returns 1 if it gives up entirely and the original cpu mask is to be
+ * returned to the kernel.
  */
-const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc,
-                                            struct cpumask *flush_mask,
-                                            struct bau_control *bcp)
+int uv_flush_send_and_wait(struct bau_desc *bau_desc,
+                          struct cpumask *flush_mask, struct bau_control *bcp)
 {
        int right_shift;
-       int uvhub;
-       int bit;
        int completion_status = 0;
        int seq_number = 0;
        long try = 0;
        int cpu = bcp->uvhub_cpu;
        int this_cpu = bcp->cpu;
-       int this_uvhub = bcp->uvhub;
        unsigned long mmr_offset;
        unsigned long index;
        cycles_t time1;
        cycles_t time2;
-       struct ptc_stats *stat = &per_cpu(ptcstats, bcp->cpu);
+       cycles_t elapsed;
+       struct ptc_stats *stat = bcp->statp;
        struct bau_control *smaster = bcp->socket_master;
        struct bau_control *hmaster = bcp->uvhub_master;
 
-       /*
-        * Spin here while there are hmaster->max_concurrent or more active
-        * descriptors. This is the per-uvhub 'throttle'.
-        */
        if (!atomic_inc_unless_ge(&hmaster->uvhub_lock,
                        &hmaster->active_descriptor_count,
-                       hmaster->max_concurrent)) {
+                       hmaster->max_bau_concurrent)) {
                stat->s_throttles++;
                do {
                        cpu_relax();
                } while (!atomic_inc_unless_ge(&hmaster->uvhub_lock,
                        &hmaster->active_descriptor_count,
-                       hmaster->max_concurrent));
+                       hmaster->max_bau_concurrent));
        }
-
        while (hmaster->uvhub_quiesce)
                cpu_relax();
 
@@ -557,23 +607,10 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc,
        }
        time1 = get_cycles();
        do {
-               /*
-                * Every message from any given cpu gets a unique message
-                * sequence number. But retries use that same number.
-                * Our message may have timed out at the destination because
-                * all sw-ack resources are in use and there is a timeout
-                * pending there.  In that case, our last send never got
-                * placed into the queue and we need to persist until it
-                * does.
-                *
-                * Make any retry a type MSG_RETRY so that the destination will
-                * free any resource held by a previous message from this cpu.
-                */
                if (try == 0) {
-                       /* use message type set by the caller the first time */
+                       bau_desc->header.msg_type = MSG_REGULAR;
                        seq_number = bcp->message_number++;
                } else {
-                       /* use RETRY type on all the rest; same sequence */
                        bau_desc->header.msg_type = MSG_RETRY;
                        stat->s_retry_messages++;
                }
@@ -581,50 +618,17 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc,
                index = (1UL << UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT) |
                        bcp->uvhub_cpu;
                bcp->send_message = get_cycles();
-
                uv_write_local_mmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
-
                try++;
                completion_status = uv_wait_completion(bau_desc, mmr_offset,
                        right_shift, this_cpu, bcp, smaster, try);
 
                if (completion_status == FLUSH_RETRY_PLUGGED) {
-                       /*
-                        * Our retries may be blocked by all destination swack
-                        * resources being consumed, and a timeout pending. In
-                        * that case hardware immediately returns the ERROR
-                        * that looks like a destination timeout.
-                        */
-                       udelay(TIMEOUT_DELAY);
-                       bcp->plugged_tries++;
-                       if (bcp->plugged_tries >= PLUGSB4RESET) {
-                               bcp->plugged_tries = 0;
-                               quiesce_local_uvhub(hmaster);
-                               spin_lock(&hmaster->queue_lock);
-                               uv_reset_with_ipi(&bau_desc->distribution,
-                                                       this_cpu);
-                               spin_unlock(&hmaster->queue_lock);
-                               end_uvhub_quiesce(hmaster);
-                               bcp->ipi_attempts++;
-                               stat->s_resets_plug++;
-                       }
+                       destination_plugged(bau_desc, bcp, hmaster, stat);
                } else if (completion_status == FLUSH_RETRY_TIMEOUT) {
-                       hmaster->max_concurrent = 1;
-                       bcp->timeout_tries++;
-                       udelay(TIMEOUT_DELAY);
-                       if (bcp->timeout_tries >= TIMEOUTSB4RESET) {
-                               bcp->timeout_tries = 0;
-                               quiesce_local_uvhub(hmaster);
-                               spin_lock(&hmaster->queue_lock);
-                               uv_reset_with_ipi(&bau_desc->distribution,
-                                                               this_cpu);
-                               spin_unlock(&hmaster->queue_lock);
-                               end_uvhub_quiesce(hmaster);
-                               bcp->ipi_attempts++;
-                               stat->s_resets_timeout++;
-                       }
+                       destination_timeout(bau_desc, bcp, hmaster, stat);
                }
-               if (bcp->ipi_attempts >= 3) {
+               if (bcp->ipi_attempts >= bcp->ipi_reset_limit) {
                        bcp->ipi_attempts = 0;
                        completion_status = FLUSH_GIVEUP;
                        break;
@@ -633,49 +637,36 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc,
        } while ((completion_status == FLUSH_RETRY_PLUGGED) ||
                 (completion_status == FLUSH_RETRY_TIMEOUT));
        time2 = get_cycles();
-
-       if ((completion_status == FLUSH_COMPLETE) && (bcp->conseccompletes > 5)
-           && (hmaster->max_concurrent < hmaster->max_concurrent_constant))
-                       hmaster->max_concurrent++;
-
-       /*
-        * hold any cpu not timing out here; no other cpu currently held by
-        * the 'throttle' should enter the activation code
-        */
+       bcp->plugged_tries = 0;
+       bcp->timeout_tries = 0;
+       if ((completion_status == FLUSH_COMPLETE) &&
+           (bcp->conseccompletes > bcp->complete_threshold) &&
+           (hmaster->max_bau_concurrent <
+                                       hmaster->max_bau_concurrent_constant))
+                       hmaster->max_bau_concurrent++;
        while (hmaster->uvhub_quiesce)
                cpu_relax();
        atomic_dec(&hmaster->active_descriptor_count);
-
-       /* guard against cycles wrap */
-       if (time2 > time1)
-               stat->s_time += (time2 - time1);
-       else
-               stat->s_requestor--; /* don't count this one */
+       if (time2 > time1) {
+               elapsed = time2 - time1;
+               stat->s_time += elapsed;
+               if ((completion_status == FLUSH_COMPLETE) && (try == 1)) {
+                       bcp->period_requests++;
+                       bcp->period_time += elapsed;
+                       if ((elapsed > congested_cycles) &&
+                           (bcp->period_requests > bcp->congested_reps)) {
+                               disable_for_congestion(bcp, stat);
+                       }
+               }
+       } else
+               stat->s_requestor--;
        if (completion_status == FLUSH_COMPLETE && try > 1)
                stat->s_retriesok++;
        else if (completion_status == FLUSH_GIVEUP) {
-               /*
-                * Cause the caller to do an IPI-style TLB shootdown on
-                * the target cpu's, all of which are still in the mask.
-                */
                stat->s_giveup++;
-               return flush_mask;
-       }
-
-       /*
-        * Success, so clear the remote cpu's from the mask so we don't
-        * use the IPI method of shootdown on them.
-        */
-       for_each_cpu(bit, flush_mask) {
-               uvhub = uv_cpu_to_blade_id(bit);
-               if (uvhub == this_uvhub)
-                       continue;
-               cpumask_clear_cpu(bit, flush_mask);
+               return 1;
        }
-       if (!cpumask_empty(flush_mask))
-               return flush_mask;
-
-       return NULL;
+       return 0;
 }
 
 /**
@@ -707,70 +698,89 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                                          struct mm_struct *mm,
                                          unsigned long va, unsigned int cpu)
 {
-       int remotes;
        int tcpu;
        int uvhub;
        int locals = 0;
+       int remotes = 0;
+       int hubs = 0;
        struct bau_desc *bau_desc;
        struct cpumask *flush_mask;
        struct ptc_stats *stat;
        struct bau_control *bcp;
+       struct bau_control *tbcp;
 
+       /* kernel was booted 'nobau' */
        if (nobau)
                return cpumask;
 
        bcp = &per_cpu(bau_control, cpu);
+       stat = bcp->statp;
+
+       /* bau was disabled due to slow response */
+       if (bcp->baudisabled) {
+               /* the cpu that disabled it must re-enable it */
+               if (bcp->set_bau_off) {
+                       if (get_cycles() >= bcp->set_bau_on_time) {
+                               stat->s_bau_reenabled++;
+                               baudisabled = 0;
+                               for_each_present_cpu(tcpu) {
+                                       tbcp = &per_cpu(bau_control, tcpu);
+                                       tbcp->baudisabled = 0;
+                                       tbcp->period_requests = 0;
+                                       tbcp->period_time = 0;
+                               }
+                       }
+               }
+               return cpumask;
+       }
+
        /*
         * Each sending cpu has a per-cpu mask which it fills from the caller's
-        * cpu mask.  Only remote cpus are converted to uvhubs and copied.
+        * cpu mask.  All cpus are converted to uvhubs and copied to the
+        * activation descriptor.
         */
        flush_mask = (struct cpumask *)per_cpu(uv_flush_tlb_mask, cpu);
-       /*
-        * copy cpumask to flush_mask, removing current cpu
-        * (current cpu should already have been flushed by the caller and
-        *  should never be returned if we return flush_mask)
-        */
+       /* don't actually do a shootdown of the local cpu */
        cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu));
        if (cpu_isset(cpu, *cpumask))
-               locals++;  /* current cpu was targeted */
+               stat->s_ntargself++;
 
        bau_desc = bcp->descriptor_base;
        bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
-
        bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
-       remotes = 0;
+
+       /* cpu statistics */
        for_each_cpu(tcpu, flush_mask) {
                uvhub = uv_cpu_to_blade_id(tcpu);
-               if (uvhub == bcp->uvhub) {
-                       locals++;
-                       continue;
-               }
                bau_uvhub_set(uvhub, &bau_desc->distribution);
-               remotes++;
-       }
-       if (remotes == 0) {
-               /*
-                * No off_hub flushing; return status for local hub.
-                * Return the caller's mask if all were local (the current
-                * cpu may be in that mask).
-                */
-               if (locals)
-                       return cpumask;
+               if (uvhub == bcp->uvhub)
+                       locals++;
                else
-                       return NULL;
+                       remotes++;
        }
-       stat = &per_cpu(ptcstats, cpu);
+       if ((locals + remotes) == 0)
+               return NULL;
        stat->s_requestor++;
-       stat->s_ntargcpu += remotes;
+       stat->s_ntargcpu += remotes + locals;
+       stat->s_ntargremotes += remotes;
+       stat->s_ntarglocals += locals;
        remotes = bau_uvhub_weight(&bau_desc->distribution);
-       stat->s_ntarguvhub += remotes;
-       if (remotes >= 16)
+
+       /* uvhub statistics */
+       hubs = bau_uvhub_weight(&bau_desc->distribution);
+       if (locals) {
+               stat->s_ntarglocaluvhub++;
+               stat->s_ntargremoteuvhub += (hubs - 1);
+       } else
+               stat->s_ntargremoteuvhub += hubs;
+       stat->s_ntarguvhub += hubs;
+       if (hubs >= 16)
                stat->s_ntarguvhub16++;
-       else if (remotes >= 8)
+       else if (hubs >= 8)
                stat->s_ntarguvhub8++;
-       else if (remotes >= 4)
+       else if (hubs >= 4)
                stat->s_ntarguvhub4++;
-       else if (remotes >= 2)
+       else if (hubs >= 2)
                stat->s_ntarguvhub2++;
        else
                stat->s_ntarguvhub1++;
@@ -779,10 +789,13 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        bau_desc->payload.sending_cpu = cpu;
 
        /*
-        * uv_flush_send_and_wait returns null if all cpu's were messaged, or
-        * the adjusted flush_mask if any cpu's were not messaged.
+        * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
+        * or 1 if it gave up and the original cpumask should be returned.
         */
-       return uv_flush_send_and_wait(bau_desc, flush_mask, bcp);
+       if (!uv_flush_send_and_wait(bau_desc, flush_mask, bcp))
+               return NULL;
+       else
+               return cpumask;
 }
 
 /*
@@ -810,7 +823,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
 
        time_start = get_cycles();
        bcp = &per_cpu(bau_control, smp_processor_id());
-       stat = &per_cpu(ptcstats, smp_processor_id());
+       stat = bcp->statp;
        msgdesc.va_queue_first = bcp->va_queue_first;
        msgdesc.va_queue_last = bcp->va_queue_last;
        msg = bcp->bau_msg_head;
@@ -908,12 +921,12 @@ static void uv_ptc_seq_stop(struct seq_file *file, void *data)
 }
 
 static inline unsigned long long
-millisec_2_cycles(unsigned long millisec)
+microsec_2_cycles(unsigned long microsec)
 {
        unsigned long ns;
        unsigned long long cyc;
 
-       ns = millisec * 1000;
+       ns = microsec * 1000;
        cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
        return cyc;
 }
@@ -931,15 +944,19 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data)
 
        if (!cpu) {
                seq_printf(file,
-                       "# cpu sent stime numuvhubs numuvhubs16 numuvhubs8 ");
+                       "# cpu sent stime self locals remotes ncpus localhub ");
                seq_printf(file,
-                       "numuvhubs4 numuvhubs2 numuvhubs1 numcpus dto ");
+                       "remotehub numuvhubs numuvhubs16 numuvhubs8 ");
+               seq_printf(file,
+                       "numuvhubs4 numuvhubs2 numuvhubs1 dto ");
                seq_printf(file,
                        "retries rok resetp resett giveup sto bz throt ");
                seq_printf(file,
                        "sw_ack recv rtime all ");
                seq_printf(file,
-                       "one mult none retry canc nocan reset rcan\n");
+                       "one mult none retry canc nocan reset rcan ");
+               seq_printf(file,
+                       "disable enable\n");
        }
        if (cpu < num_possible_cpus() && cpu_online(cpu)) {
                stat = &per_cpu(ptcstats, cpu);
@@ -947,18 +964,23 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data)
                seq_printf(file,
                        "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
                           cpu, stat->s_requestor, cycles_2_us(stat->s_time),
-                          stat->s_ntarguvhub, stat->s_ntarguvhub16,
+                          stat->s_ntargself, stat->s_ntarglocals,
+                          stat->s_ntargremotes, stat->s_ntargcpu,
+                          stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub,
+                          stat->s_ntarguvhub, stat->s_ntarguvhub16);
+               seq_printf(file, "%ld %ld %ld %ld %ld ",
                           stat->s_ntarguvhub8, stat->s_ntarguvhub4,
                           stat->s_ntarguvhub2, stat->s_ntarguvhub1,
-                          stat->s_ntargcpu, stat->s_dtimeout);
+                          stat->s_dtimeout);
                seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ",
                           stat->s_retry_messages, stat->s_retriesok,
                           stat->s_resets_plug, stat->s_resets_timeout,
                           stat->s_giveup, stat->s_stimeout,
                           stat->s_busy, stat->s_throttles);
+
                /* destination side statistics */
                seq_printf(file,
-                          "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
+                          "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
                           uv_read_global_mmr64(uv_cpu_to_pnode(cpu),
                                        UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE),
                           stat->d_requestee, cycles_2_us(stat->d_time),
@@ -966,15 +988,36 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data)
                           stat->d_nomsg, stat->d_retries, stat->d_canceled,
                           stat->d_nocanceled, stat->d_resets,
                           stat->d_rcanceled);
+               seq_printf(file, "%ld %ld\n",
+                       stat->s_bau_disabled, stat->s_bau_reenabled);
        }
 
        return 0;
 }
 
+/*
+ * Display the tunables thru debugfs
+ */
+static ssize_t tunables_read(struct file *file, char __user *userbuf,
+                                               size_t count, loff_t *ppos)
+{
+       char buf[300];
+       int ret;
+
+       ret = snprintf(buf, 300, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
+               "max_bau_concurrent plugged_delay plugsb4reset",
+               "timeoutsb4reset ipi_reset_limit complete_threshold",
+               "congested_response_us congested_reps congested_period",
+               max_bau_concurrent, plugged_delay, plugsb4reset,
+               timeoutsb4reset, ipi_reset_limit, complete_threshold,
+               congested_response_us, congested_reps, congested_period);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+}
+
 /*
  * -1: resetf the statistics
  *  0: display meaning of the statistics
- * >0: maximum concurrent active descriptors per uvhub (throttle)
  */
 static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user,
                                 size_t count, loff_t *data)
@@ -983,7 +1026,6 @@ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user,
        long input_arg;
        char optstr[64];
        struct ptc_stats *stat;
-       struct bau_control *bcp;
 
        if (count == 0 || count > sizeof(optstr))
                return -EINVAL;
@@ -1059,29 +1101,158 @@ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user,
                "reset:    number of ipi-style reset requests processed\n");
                printk(KERN_DEBUG
                "rcan:     number messages canceled by reset requests\n");
+               printk(KERN_DEBUG
+               "disable:  number times use of the BAU was disabled\n");
+               printk(KERN_DEBUG
+               "enable:   number times use of the BAU was re-enabled\n");
        } else if (input_arg == -1) {
                for_each_present_cpu(cpu) {
                        stat = &per_cpu(ptcstats, cpu);
                        memset(stat, 0, sizeof(struct ptc_stats));
                }
-       } else {
-               uv_bau_max_concurrent = input_arg;
-               bcp = &per_cpu(bau_control, smp_processor_id());
-               if (uv_bau_max_concurrent < 1 ||
-                   uv_bau_max_concurrent > bcp->cpus_in_uvhub) {
-                       printk(KERN_DEBUG
-                               "Error: BAU max concurrent %d; %d is invalid\n",
-                               bcp->max_concurrent, uv_bau_max_concurrent);
-                       return -EINVAL;
-               }
-               printk(KERN_DEBUG "Set BAU max concurrent:%d\n",
-                      uv_bau_max_concurrent);
-               for_each_present_cpu(cpu) {
-                       bcp = &per_cpu(bau_control, cpu);
-                       bcp->max_concurrent = uv_bau_max_concurrent;
+       }
+
+       return count;
+}
+
+static int local_atoi(const char *name)
+{
+       int val = 0;
+
+       for (;; name++) {
+               switch (*name) {
+               case '0' ... '9':
+                       val = 10*val+(*name-'0');
+                       break;
+               default:
+                       return val;
                }
        }
+}
+
+/*
+ * set the tunables
+ * 0 values reset them to defaults
+ */
+static ssize_t tunables_write(struct file *file, const char __user *user,
+                                size_t count, loff_t *data)
+{
+       int cpu;
+       int cnt = 0;
+       int val;
+       char *p;
+       char *q;
+       char instr[64];
+       struct bau_control *bcp;
+
+       if (count == 0 || count > sizeof(instr)-1)
+               return -EINVAL;
+       if (copy_from_user(instr, user, count))
+               return -EFAULT;
+
+       instr[count] = '\0';
+       /* count the fields */
+       p = instr + strspn(instr, WHITESPACE);
+       q = p;
+       for (; *p; p = q + strspn(q, WHITESPACE)) {
+               q = p + strcspn(p, WHITESPACE);
+               cnt++;
+               if (q == p)
+                       break;
+       }
+       if (cnt != 9) {
+               printk(KERN_INFO "bau tunable error: should be 9 numbers\n");
+               return -EINVAL;
+       }
 
+       p = instr + strspn(instr, WHITESPACE);
+       q = p;
+       for (cnt = 0; *p; p = q + strspn(q, WHITESPACE), cnt++) {
+               q = p + strcspn(p, WHITESPACE);
+               val = local_atoi(p);
+               switch (cnt) {
+               case 0:
+                       if (val == 0) {
+                               max_bau_concurrent = MAX_BAU_CONCURRENT;
+                               max_bau_concurrent_constant =
+                                                       MAX_BAU_CONCURRENT;
+                               continue;
+                       }
+                       bcp = &per_cpu(bau_control, smp_processor_id());
+                       if (val < 1 || val > bcp->cpus_in_uvhub) {
+                               printk(KERN_DEBUG
+                               "Error: BAU max concurrent %d is invalid\n",
+                               val);
+                               return -EINVAL;
+                       }
+                       max_bau_concurrent = val;
+                       max_bau_concurrent_constant = val;
+                       continue;
+               case 1:
+                       if (val == 0)
+                               plugged_delay = PLUGGED_DELAY;
+                       else
+                               plugged_delay = val;
+                       continue;
+               case 2:
+                       if (val == 0)
+                               plugsb4reset = PLUGSB4RESET;
+                       else
+                               plugsb4reset = val;
+                       continue;
+               case 3:
+                       if (val == 0)
+                               timeoutsb4reset = TIMEOUTSB4RESET;
+                       else
+                               timeoutsb4reset = val;
+                       continue;
+               case 4:
+                       if (val == 0)
+                               ipi_reset_limit = IPI_RESET_LIMIT;
+                       else
+                               ipi_reset_limit = val;
+                       continue;
+               case 5:
+                       if (val == 0)
+                               complete_threshold = COMPLETE_THRESHOLD;
+                       else
+                               complete_threshold = val;
+                       continue;
+               case 6:
+                       if (val == 0)
+                               congested_response_us = CONGESTED_RESPONSE_US;
+                       else
+                               congested_response_us = val;
+                       continue;
+               case 7:
+                       if (val == 0)
+                               congested_reps = CONGESTED_REPS;
+                       else
+                               congested_reps = val;
+                       continue;
+               case 8:
+                       if (val == 0)
+                               congested_period = CONGESTED_PERIOD;
+                       else
+                               congested_period = val;
+                       continue;
+               }
+               if (q == p)
+                       break;
+       }
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->max_bau_concurrent = max_bau_concurrent;
+               bcp->max_bau_concurrent_constant = max_bau_concurrent;
+               bcp->plugged_delay = plugged_delay;
+               bcp->plugsb4reset = plugsb4reset;
+               bcp->timeoutsb4reset = timeoutsb4reset;
+               bcp->ipi_reset_limit = ipi_reset_limit;
+               bcp->complete_threshold = complete_threshold;
+               bcp->congested_response_us = congested_response_us;
+               bcp->congested_reps = congested_reps;
+               bcp->congested_period = congested_period;
+       }
        return count;
 }
 
@@ -1097,6 +1268,11 @@ static int uv_ptc_proc_open(struct inode *inode, struct file *file)
        return seq_open(file, &uv_ptc_seq_ops);
 }
 
+static int tunables_open(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
 static const struct file_operations proc_uv_ptc_operations = {
        .open           = uv_ptc_proc_open,
        .read           = seq_read,
@@ -1105,6 +1281,12 @@ static const struct file_operations proc_uv_ptc_operations = {
        .release        = seq_release,
 };
 
+static const struct file_operations tunables_fops = {
+       .open           = tunables_open,
+       .read           = tunables_read,
+       .write          = tunables_write,
+};
+
 static int __init uv_ptc_init(void)
 {
        struct proc_dir_entry *proc_uv_ptc;
@@ -1119,6 +1301,20 @@ static int __init uv_ptc_init(void)
                       UV_PTC_BASENAME);
                return -EINVAL;
        }
+
+       tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL);
+       if (!tunables_dir) {
+               printk(KERN_ERR "unable to create debugfs directory %s\n",
+                      UV_BAU_TUNABLES_DIR);
+               return -EINVAL;
+       }
+       tunables_file = debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600,
+                       tunables_dir, NULL, &tunables_fops);
+       if (!tunables_file) {
+               printk(KERN_ERR "unable to create debugfs file %s\n",
+                      UV_BAU_TUNABLES_FILE);
+               return -EINVAL;
+       }
        return 0;
 }
 
@@ -1258,16 +1454,45 @@ static void __init uv_init_uvhub(int uvhub, int vector)
                                      ((apicid << 32) | vector));
 }
 
+/*
+ * We will set BAU_MISC_CONTROL with a timeout period.
+ * But the BIOS has set UVH_AGING_PRESCALE_SEL and UVH_TRANSACTION_TIMEOUT.
+ * So the destination timeout period has be be calculated from them.
+ */
+static int
+calculate_destination_timeout(void)
+{
+       unsigned long mmr_image;
+       int mult1;
+       int mult2;
+       int index;
+       int base;
+       int ret;
+       unsigned long ts_ns;
+
+       mult1 = UV_INTD_SOFT_ACK_TIMEOUT_PERIOD & BAU_MISC_CONTROL_MULT_MASK;
+       mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
+       index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK;
+       mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT);
+       mult2 = (mmr_image >> BAU_TRANS_SHIFT) & BAU_TRANS_MASK;
+       base = timeout_base_ns[index];
+       ts_ns = base * mult1 * mult2;
+       ret = ts_ns / 1000;
+       return ret;
+}
+
 /*
  * initialize the bau_control structure for each cpu
  */
 static void uv_init_per_cpu(int nuvhubs)
 {
-       int i, j, k;
+       int i;
        int cpu;
        int pnode;
        int uvhub;
        short socket = 0;
+       unsigned short socket_mask;
+       unsigned int uvhub_mask;
        struct bau_control *bcp;
        struct uvhub_desc *bdp;
        struct socket_desc *sdp;
@@ -1278,7 +1503,7 @@ static void uv_init_per_cpu(int nuvhubs)
                short cpu_number[16];
        };
        struct uvhub_desc {
-               short num_sockets;
+               unsigned short socket_mask;
                short num_cpus;
                short uvhub;
                short pnode;
@@ -1286,57 +1511,83 @@ static void uv_init_per_cpu(int nuvhubs)
        };
        struct uvhub_desc *uvhub_descs;
 
+       timeout_us = calculate_destination_timeout();
+
        uvhub_descs = (struct uvhub_desc *)
                kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL);
        memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc));
        for_each_present_cpu(cpu) {
                bcp = &per_cpu(bau_control, cpu);
                memset(bcp, 0, sizeof(struct bau_control));
-               spin_lock_init(&bcp->masks_lock);
-               bcp->max_concurrent = uv_bau_max_concurrent;
                pnode = uv_cpu_hub_info(cpu)->pnode;
                uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
+               uvhub_mask |= (1 << uvhub);
                bdp = &uvhub_descs[uvhub];
                bdp->num_cpus++;
                bdp->uvhub = uvhub;
                bdp->pnode = pnode;
-               /* time interval to catch a hardware stay-busy bug */
-               bcp->timeout_interval = millisec_2_cycles(3);
-               /* kludge: assume uv_hub.h is constant */
-               socket = (cpu_physical_id(cpu)>>5)&1;
-               if (socket >= bdp->num_sockets)
-                       bdp->num_sockets = socket+1;
+               /* kludge: 'assuming' one node per socket, and assuming that
+                  disabling a socket just leaves a gap in node numbers */
+               socket = (cpu_to_node(cpu) & 1);;
+               bdp->socket_mask |= (1 << socket);
                sdp = &bdp->socket[socket];
                sdp->cpu_number[sdp->num_cpus] = cpu;
                sdp->num_cpus++;
        }
-       socket = 0;
-       for_each_possible_blade(uvhub) {
+       uvhub = 0;
+       while (uvhub_mask) {
+               if (!(uvhub_mask & 1))
+                       goto nexthub;
                bdp = &uvhub_descs[uvhub];
-               for (i = 0; i < bdp->num_sockets; i++) {
-                       sdp = &bdp->socket[i];
-                       for (j = 0; j < sdp->num_cpus; j++) {
-                               cpu = sdp->cpu_number[j];
+               socket_mask = bdp->socket_mask;
+               socket = 0;
+               while (socket_mask) {
+                       if (!(socket_mask & 1))
+                               goto nextsocket;
+                       sdp = &bdp->socket[socket];
+                       for (i = 0; i < sdp->num_cpus; i++) {
+                               cpu = sdp->cpu_number[i];
                                bcp = &per_cpu(bau_control, cpu);
                                bcp->cpu = cpu;
-                               if (j == 0) {
+                               if (i == 0) {
                                        smaster = bcp;
-                                       if (i == 0)
+                                       if (socket == 0)
                                                hmaster = bcp;
                                }
                                bcp->cpus_in_uvhub = bdp->num_cpus;
                                bcp->cpus_in_socket = sdp->num_cpus;
                                bcp->socket_master = smaster;
+                               bcp->uvhub = bdp->uvhub;
                                bcp->uvhub_master = hmaster;
-                               for (k = 0; k < DEST_Q_SIZE; k++)
-                                       bcp->socket_acknowledge_count[k] = 0;
-                               bcp->uvhub_cpu =
-                                 uv_cpu_hub_info(cpu)->blade_processor_id;
+                               bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->
+                                               blade_processor_id;
                        }
+nextsocket:
                        socket++;
+                       socket_mask = (socket_mask >> 1);
                }
+nexthub:
+               uvhub++;
+               uvhub_mask = (uvhub_mask >> 1);
        }
        kfree(uvhub_descs);
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->baudisabled = 0;
+               bcp->statp = &per_cpu(ptcstats, cpu);
+               /* time interval to catch a hardware stay-busy bug */
+               bcp->timeout_interval = microsec_2_cycles(2*timeout_us);
+               bcp->max_bau_concurrent = max_bau_concurrent;
+               bcp->max_bau_concurrent_constant = max_bau_concurrent;
+               bcp->plugged_delay = plugged_delay;
+               bcp->plugsb4reset = plugsb4reset;
+               bcp->timeoutsb4reset = timeoutsb4reset;
+               bcp->ipi_reset_limit = ipi_reset_limit;
+               bcp->complete_threshold = complete_threshold;
+               bcp->congested_response_us = congested_response_us;
+               bcp->congested_reps = congested_reps;
+               bcp->congested_period = congested_period;
+       }
 }
 
 /*
@@ -1361,10 +1612,11 @@ static int __init uv_bau_init(void)
                zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu),
                                       GFP_KERNEL, cpu_to_node(cur_cpu));
 
-       uv_bau_max_concurrent = MAX_BAU_CONCURRENT;
        uv_nshift = uv_hub_info->m_val;
        uv_mmask = (1UL << uv_hub_info->m_val) - 1;
        nuvhubs = uv_num_possible_blades();
+       spin_lock_init(&disable_lock);
+       congested_cycles = microsec_2_cycles(congested_response_us);
 
        uv_init_per_cpu(nuvhubs);
 
@@ -1383,15 +1635,19 @@ static int __init uv_bau_init(void)
        alloc_intr_gate(vector, uv_bau_message_intr1);
 
        for_each_possible_blade(uvhub) {
-               pnode = uv_blade_to_pnode(uvhub);
-               /* INIT the bau */
-               uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL,
-                                     ((unsigned long)1 << 63));
-               mmr = 1; /* should be 1 to broadcast to both sockets */
-               uv_write_global_mmr64(pnode, UVH_BAU_DATA_BROADCAST, mmr);
+               if (uv_blade_nr_possible_cpus(uvhub)) {
+                       pnode = uv_blade_to_pnode(uvhub);
+                       /* INIT the bau */
+                       uv_write_global_mmr64(pnode,
+                                       UVH_LB_BAU_SB_ACTIVATION_CONTROL,
+                                       ((unsigned long)1 << 63));
+                       mmr = 1; /* should be 1 to broadcast to both sockets */
+                       uv_write_global_mmr64(pnode, UVH_BAU_DATA_BROADCAST,
+                                               mmr);
+               }
        }
 
        return 0;
 }
 core_initcall(uv_bau_init);
-core_initcall(uv_ptc_init);
+fs_initcall(uv_ptc_init);
index 4a5979aa6883addce8921161b68bc9d8b7206ffc..2cda60a06e654ae6e66c5f8f4dadb1f85c5b7b1d 100644 (file)
        CFI_ADJUST_CFA_OFFSET -4
 .endm
 
-.macro BEGIN func reg
-$v = \reg
-
-ENTRY(atomic64_\func\()_386)
-       CFI_STARTPROC
-       LOCK $v
-
-.macro RETURN
-       UNLOCK $v
+#define BEGIN(op) \
+.macro endp; \
+       CFI_ENDPROC; \
+ENDPROC(atomic64_##op##_386); \
+.purgem endp; \
+.endm; \
+ENTRY(atomic64_##op##_386); \
+       CFI_STARTPROC; \
+       LOCK v;
+
+#define ENDP endp
+
+#define RET \
+       UNLOCK v; \
        ret
-.endm
-
-.macro END_
-       CFI_ENDPROC
-ENDPROC(atomic64_\func\()_386)
-.purgem RETURN
-.purgem END_
-.purgem END
-.endm
-
-.macro END
-RETURN
-END_
-.endm
-.endm
 
-BEGIN read %ecx
-       movl  ($v), %eax
-       movl 4($v), %edx
-END
-
-BEGIN set %esi
-       movl %ebx,  ($v)
-       movl %ecx, 4($v)
-END
-
-BEGIN xchg %esi
-       movl  ($v), %eax
-       movl 4($v), %edx
-       movl %ebx,  ($v)
-       movl %ecx, 4($v)
-END
-
-BEGIN add %ecx
-       addl %eax,  ($v)
-       adcl %edx, 4($v)
-END
-
-BEGIN add_return %ecx
-       addl  ($v), %eax
-       adcl 4($v), %edx
-       movl %eax,  ($v)
-       movl %edx, 4($v)
-END
-
-BEGIN sub %ecx
-       subl %eax,  ($v)
-       sbbl %edx, 4($v)
-END
-
-BEGIN sub_return %ecx
+#define RET_ENDP \
+       RET; \
+       ENDP
+
+#define v %ecx
+BEGIN(read)
+       movl  (v), %eax
+       movl 4(v), %edx
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(set)
+       movl %ebx,  (v)
+       movl %ecx, 4(v)
+RET_ENDP
+#undef v
+
+#define v  %esi
+BEGIN(xchg)
+       movl  (v), %eax
+       movl 4(v), %edx
+       movl %ebx,  (v)
+       movl %ecx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(add)
+       addl %eax,  (v)
+       adcl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(add_return)
+       addl  (v), %eax
+       adcl 4(v), %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(sub)
+       subl %eax,  (v)
+       sbbl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(sub_return)
        negl %edx
        negl %eax
        sbbl $0, %edx
-       addl  ($v), %eax
-       adcl 4($v), %edx
-       movl %eax,  ($v)
-       movl %edx, 4($v)
-END
-
-BEGIN inc %esi
-       addl $1,  ($v)
-       adcl $0, 4($v)
-END
-
-BEGIN inc_return %esi
-       movl  ($v), %eax
-       movl 4($v), %edx
+       addl  (v), %eax
+       adcl 4(v), %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(inc)
+       addl $1,  (v)
+       adcl $0, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(inc_return)
+       movl  (v), %eax
+       movl 4(v), %edx
        addl $1, %eax
        adcl $0, %edx
-       movl %eax,  ($v)
-       movl %edx, 4($v)
-END
-
-BEGIN dec %esi
-       subl $1,  ($v)
-       sbbl $0, 4($v)
-END
-
-BEGIN dec_return %esi
-       movl  ($v), %eax
-       movl 4($v), %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(dec)
+       subl $1,  (v)
+       sbbl $0, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(dec_return)
+       movl  (v), %eax
+       movl 4(v), %edx
        subl $1, %eax
        sbbl $0, %edx
-       movl %eax,  ($v)
-       movl %edx, 4($v)
-END
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
 
-BEGIN add_unless %ecx
+#define v %ecx
+BEGIN(add_unless)
        addl %eax, %esi
        adcl %edx, %edi
-       addl  ($v), %eax
-       adcl 4($v), %edx
+       addl  (v), %eax
+       adcl 4(v), %edx
        cmpl %eax, %esi
        je 3f
 1:
-       movl %eax,  ($v)
-       movl %edx, 4($v)
+       movl %eax,  (v)
+       movl %edx, 4(v)
        movl $1, %eax
 2:
-RETURN
+       RET
 3:
        cmpl %edx, %edi
        jne 1b
        xorl %eax, %eax
        jmp 2b
-END_
+ENDP
+#undef v
 
-BEGIN inc_not_zero %esi
-       movl  ($v), %eax
-       movl 4($v), %edx
+#define v %esi
+BEGIN(inc_not_zero)
+       movl  (v), %eax
+       movl 4(v), %edx
        testl %eax, %eax
        je 3f
 1:
        addl $1, %eax
        adcl $0, %edx
-       movl %eax,  ($v)
-       movl %edx, 4($v)
+       movl %eax,  (v)
+       movl %edx, 4(v)
        movl $1, %eax
 2:
-RETURN
+       RET
 3:
        testl %edx, %edx
        jne 1b
        jmp 2b
-END_
+ENDP
+#undef v
 
-BEGIN dec_if_positive %esi
-       movl  ($v), %eax
-       movl 4($v), %edx
+#define v %esi
+BEGIN(dec_if_positive)
+       movl  (v), %eax
+       movl 4(v), %edx
        subl $1, %eax
        sbbl $0, %edx
        js 1f
-       movl %eax,  ($v)
-       movl %edx, 4($v)
+       movl %eax,  (v)
+       movl %edx, 4(v)
 1:
-END
+RET_ENDP
+#undef v
index f62777940dfbcc1ef534f9a90dbd96873ba453e1..4c4508e8a2043015c1cce3eb49a46c0c435e9297 100644 (file)
@@ -802,8 +802,10 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
        up_read(&mm->mmap_sem);
 
        /* Kernel mode? Handle exceptions or die: */
-       if (!(error_code & PF_USER))
+       if (!(error_code & PF_USER)) {
                no_context(regs, error_code, address);
+               return;
+       }
 
        /* User-space => ok to do another page fault: */
        if (is_prefetch(regs, error_code, address))
index 1ba67dc8006ab700170afb6964954c33c5705591..f6b48f6c595176a59c8e2fe5fa145bc11acca118 100644 (file)
@@ -668,6 +668,7 @@ static int __init ppro_init(char **cpu_type)
                *cpu_type = "i386/core_2";
                break;
        case 0x1a:
+       case 0x1e:
        case 0x2e:
                spec = &op_arch_perfmon_spec;
                *cpu_type = "i386/core_i7";
index f167e0f5e05e524b6deffbbda3127da8ae3905c8..7c2f38f68ebb5196e67f6a896a5a09ebce343179 100644 (file)
@@ -318,7 +318,7 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
  */
 
 asmlinkage
-long xtensa_execve(char __user *name, char __user * __user *argv,
+long xtensa_execve(const char __user *name, char __user * __user *argv,
                    char __user * __user *envp,
                    long a3, long a4, long a5,
                    struct pt_regs *regs)
index fbf94cf496f05923e40da77f72f8a85bb70f6a85..ea0b3863ad0fbd8afde0d4f5631081163222a26d 100644 (file)
@@ -77,7 +77,7 @@ config ZCRYPT
 
 config ZCRYPT_MONOLITHIC
        bool "Monolithic zcrypt module"
-       depends on ZCRYPT="m"
+       depends on ZCRYPT
        help
          Select this option if you want to have a single module z90crypt,
          that contains all parts of the crypto device driver (ap bus,
index e90694fe0d5ca33483ac1ba70cb5ef7e839d8f13..0bc86204213e187106c54c560774884ac632f09d 100644 (file)
@@ -139,7 +139,7 @@ static int __init amijoy_init(void)
                amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
                        BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
                for (j = 0; j < 2; j++) {
-                       XXinput_set_abs_params(amijoy_dev[i], ABS_X + j,
+                       input_set_abs_params(amijoy_dev[i], ABS_X + j,
                                             -1, 1, 0, 0);
                }
 
index ddd5afd301d456013ff7abba410b104e2c6e8d9b..dcc86b97a1535c6a3ba098543d691ee249d56cf5 100644 (file)
@@ -235,7 +235,7 @@ static void hil_dev_handle_ptr_events(struct hil_dev *ptr)
                        if (val < input_abs_min(dev, ABS_X + i))
                                input_abs_set_min(dev, ABS_X + i, val);
                        if (val > input_abs_max(dev, ABS_X + i))
-                               XXinput_abs_set_max(dev, ABS_X + i, val);
+                               input_abs_set_max(dev, ABS_X + i, val);
 #endif
                        if (i % 3)
                                val = input_abs_max(dev, ABS_X + i) - val;
@@ -391,7 +391,7 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr)
                        int diff = input_abs_max(input_dev, ABS_X + i) / 10;
                        input_abs_set_min(input_dev, ABS_X + i,
                                input_abs_min(input_dev, ABS_X + i) + diff)
-                       XXinput_abs_set_max(input_dev, ABS_X + i,
+                       input_abs_set_max(input_dev, ABS_X + i,
                                input_abs_max(input_dev, ABS_X + i) - diff)
                }
 #endif
index 7715d3242ec81849dbd725cbbaaf52a7cd597380..d3530f6e8115350668b148377d61a85256883a0a 100644 (file)
@@ -1273,6 +1273,7 @@ static int __devinit c4_probe(struct pci_dev *dev,
        if (retval != 0) {
                printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
                       nr, param.port, param.irq, param.membase);
+               pci_disable_device(dev);
                return -ENODEV;
        }
        return 0;
index 5a3f830980185c45614fb4fbf59f51924032223c..a79eb5afb92dda279d7634b51bd20a0e047ace40 100644 (file)
@@ -210,6 +210,7 @@ static int __devinit t1pci_probe(struct pci_dev *dev,
        if (retval != 0) {
                printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
                       param.port, param.irq, param.membase);
+               pci_disable_device(dev);
                return -ENODEV;
        }
        return 0;
index d2dd61d65d519687fbb20493627b8d62045e37d2..af25e1f3efd4a784daa5aa78128e908e07cef648 100644 (file)
@@ -1094,6 +1094,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                pr_info("mISDN: do not have informations about adapter at %s\n",
                        pci_name(pdev));
                kfree(card);
+               pci_disable_device(pdev);
                return -EINVAL;
        } else
                pr_notice("mISDN: found adapter %s at %s\n",
@@ -1103,7 +1104,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_drvdata(pdev, card);
        err = setup_instance(card);
        if (err) {
-               pci_disable_device(card->pdev);
+               pci_disable_device(pdev);
                kfree(card);
                pci_set_drvdata(pdev, NULL);
        } else if (ent->driver_data == INF_SCT_1) {
@@ -1114,6 +1115,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
                        if (!sc) {
                                release_card(card);
+                               pci_disable_device(pdev);
                                return -ENOMEM;
                        }
                        sc->irq = card->irq;
@@ -1121,6 +1123,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        sc->ci = card->ci + i;
                        err = setup_instance(sc);
                        if (err) {
+                               pci_disable_device(pdev);
                                kfree(sc);
                                release_card(card);
                                break;
index 30e04915a256d7da20049412fcae1f7883cdf23b..490c57cc4cfe2550be9ce60253d045617e975c16 100644 (file)
@@ -2,14 +2,21 @@ menuconfig IR_CORE
        tristate "Infrared remote controller adapters"
        depends on INPUT
        default INPUT
+       ---help---
+         Enable support for Remote Controllers on Linux. This is
+         needed in order to support several video capture adapters.
 
-if IR_CORE
+         Enable this option if you have a video capture board even
+         if you don't need IR, as otherwise, you may not be able to
+         compile the driver for your adapter.
 
 config VIDEO_IR
        tristate
        depends on IR_CORE
        default IR_CORE
 
+if IR_CORE
+
 config LIRC
        tristate
        default y
index 695239227cb784a0e9011a6f019cef1eb9a638e8..a6ceb08f11838c0504f0fe32abf33920749cb124 100644 (file)
@@ -9,7 +9,7 @@ config DVB_DM1105
        select DVB_CX24116 if !DVB_FE_CUSTOMISE
        select DVB_SI21XX if !DVB_FE_CUSTOMISE
        select DVB_DS3000 if !DVB_FE_CUSTOMISE
-       select VIDEO_IR
+       depends on VIDEO_IR
        help
          Support for cards based on the SDMC DM1105 PCI chip like
          DvbWorld 2002
index 553b48ac1919068cddaa461e7302e3d004b54c4f..fdc19bba212815ffa90de5943155535f95ab6b47 100644 (file)
@@ -1,6 +1,6 @@
 config DVB_USB
        tristate "Support for various USB DVB devices"
-       depends on DVB_CORE && USB && I2C && INPUT
+       depends on DVB_CORE && USB && I2C && IR_CORE
        help
          By enabling this you will be able to choose the various supported
          USB1.1 and USB2.0 DVB devices.
index 85a222c4eaa0606fb7f64da99ba43ce99b3516eb..e520bceee0af451177cad22ca2e4394516c3969a 100644 (file)
@@ -4,7 +4,7 @@
 
 config SMS_SIANO_MDTV
        tristate "Siano SMS1xxx based MDTV receiver"
-       depends on DVB_CORE && INPUT && HAS_DMA
+       depends on DVB_CORE && IR_CORE && HAS_DMA
        ---help---
          Choose Y or M here if you have MDTV receiver with a Siano chipset.
 
index 32a7ec65ec42f1c40fbb4e4576b56cded5045902..debea8d1d31cff05194c767aafdc5286aecc5592 100644 (file)
@@ -98,7 +98,7 @@ config DVB_BUDGET_CI
        select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        select DVB_TDA10023 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-       select VIDEO_IR
+       depends on VIDEO_IR
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
index 3077c45015f594e8c963c470fad2c07d81cf341a..1a4a89fdf767c062cf039d836361cc1007ffa6a8 100644 (file)
@@ -4,7 +4,7 @@ config VIDEO_BT848
        select I2C_ALGOBIT
        select VIDEO_BTCX
        select VIDEOBUF_DMA_SG
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
index baf7e91ee0f5a6ffd07c8b0c75e5337a038ccec1..76c054d1eef95513c95823887683728d2e81ec3b 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_CX18
        depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
        depends on INPUT        # due to VIDEO_IR
        select I2C_ALGOBIT
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
index 477d4ab5e9acbba448dec8b2a5c57ecb1804cde3..5ac7eceececa49002126ab0aa73aa09776c6e348 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_CX231XX
        depends on VIDEO_DEV && I2C && INPUT
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEOBUF_VMALLOC
        select VIDEO_CX25840
 
index 768f000e4b21eeed9078226aff99a3f54c44703c..e1367b35647afc4c2bc53992851ab4548c545a61 100644 (file)
@@ -5,7 +5,7 @@ config VIDEO_CX23885
        select VIDEO_BTCX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select IR_CORE
+       depends on IR_CORE
        select VIDEOBUF_DVB
        select VIDEOBUF_DMA_SG
        select VIDEO_CX25840
index c7e5851d3486c710d4415099582e4b1f1ee71bb9..99dbae1175919befc55ae7e2e00a3a524f666053 100644 (file)
@@ -6,7 +6,7 @@ config VIDEO_CX88
        select VIDEOBUF_DMA_SG
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for Conexant 2388x based
index c7be0e097828b93048e73426c32e25e1744019d7..66aefd6eef5577ceb2ac012b0c92a9e30b7c26a0 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_EM28XX
        depends on VIDEO_DEV && I2C && INPUT
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEOBUF_VMALLOC
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
index c46bfb1569e31d076bf248dc069ab354c330934f..be4af1fa557e421b012ad48c63dcc57e63caebfa 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_IVTV
        depends on VIDEO_V4L2 && PCI && I2C
        depends on INPUT   # due to VIDEO_IR
        select I2C_ALGOBIT
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
index 22bfd62c9551589229aad5cd8d80f335c8c1a4eb..fda005e01670823b164d7efa61d9cb9665c45d50 100644 (file)
@@ -2,7 +2,7 @@ config VIDEO_SAA7134
        tristate "Philips SAA7134 support"
        depends on VIDEO_DEV && PCI && I2C && INPUT
        select VIDEOBUF_DMA_SG
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select CRC32
index 2c29ec659b4ea308b71ef48c81d2618dd9bccef4..1686ebfa6951a17cd2994c0da1181f16c9881df2 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_TLG2300
        depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEOBUF_VMALLOC
        select SND_PCM
        select VIDEOBUF_DVB
index d2f20c2acae2e99b7dd52c623f2158e6abcabc55..073f01390cdd0a00de7e34dc7cd30360b72912c4 100644 (file)
@@ -228,11 +228,6 @@ static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        if (file->f_op->unlocked_ioctl)
                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
-       else if (file->f_op->ioctl) {
-               lock_kernel();
-               ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
-               unlock_kernel();
-       }
 
        return ret;
 }
@@ -973,7 +968,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret = -ENOIOCTLCMD;
 
-       if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
+       if (!file->f_op->unlocked_ioctl)
                return ret;
 
        switch (cmd) {
index 84c1a53a727ac97a56cfa44166b443cd36a90df3..ea8d32cd425d9f1b06cdbb95749bf302ac43e033 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/ctype.h>
+#include <linux/slab.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
index 077ccf840edf24dc46107334c39c5758de248465..2111dbfea6feb8b53f56e73567e54fd4d11a818b 100644 (file)
 #include <net/caif/caif_spi.h>
 
 #ifndef CONFIG_CAIF_SPI_SYNC
-#define SPI_DATA_POS SPI_CMD_SZ
+#define SPI_DATA_POS 0
 static inline int forward_to_spi_cmd(struct cfspi *cfspi)
 {
        return cfspi->rx_cpck_len;
 }
 #else
-#define SPI_DATA_POS 0
+#define SPI_DATA_POS SPI_CMD_SZ
 static inline int forward_to_spi_cmd(struct cfspi *cfspi)
 {
        return 0;
index 4eb6f986703bec69686b8def0677535a760aac61..f5819526b5ee90c25a8630a63fc81f04b64ffb0e 100644 (file)
@@ -808,6 +808,7 @@ xirc2ps_config(struct pcmcia_device * link)
     }
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+    link->io_lines = 10;
     if (local->modem) {
        int pass;
 
@@ -839,7 +840,6 @@ xirc2ps_config(struct pcmcia_device * link)
        }
        printk(KNOT_XIRC "no ports available\n");
     } else {
-       link->io_lines = 10;
        link->resource[0]->end = 16;
        for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
            link->resource[0]->start = ioaddr;
index a527e37728cd9fe4566445b78bd2c1cf47bc0a88..eb799b36c86a391f90bb7f07074257084f4047ba 100644 (file)
@@ -5,7 +5,7 @@
 menuconfig PHYLIB
        tristate "PHY Device support and infrastructure"
        depends on !S390
-       depends on NET_ETHERNET
+       depends on NETDEVICES
        help
          Ethernet controllers are usually attached to PHY
          devices.  This option provides infrastructure for
index 5130db8f5c4ec4b2ced76a400071814c3e638c60..1bb16cb794331ba975eddcc5327f1fc13ef495c9 100644 (file)
@@ -301,7 +301,7 @@ EXPORT_SYMBOL(phy_ethtool_gset);
 /**
  * phy_mii_ioctl - generic PHY MII ioctl interface
  * @phydev: the phy_device struct
- * @mii_data: MII ioctl data
+ * @ifr: &struct ifreq for socket ioctl's
  * @cmd: ioctl cmd to execute
  *
  * Note that this function is currently incompatible with the
index b9615bd745ea5d9175e6d6153d5c924084d550d2..bf6d87adda4fff7a5aa1d1e20728383d08e621f1 100644 (file)
@@ -473,48 +473,58 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
 static int
 qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
 {
-       struct qlcnic_pci_info pci_info[QLCNIC_MAX_PCI_FUNC];
+       struct qlcnic_pci_info *pci_info;
        int i, ret = 0, err;
        u8 pfn;
 
-       if (!adapter->npars)
-               adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
-                               QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
-       if (!adapter->npars)
+       pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+       if (!pci_info)
                return -ENOMEM;
 
-       if (!adapter->eswitch)
-               adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
+       adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
+                               QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
+       if (!adapter->npars) {
+               err = -ENOMEM;
+               goto err_pci_info;
+       }
+
+       adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
                                QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
        if (!adapter->eswitch) {
                err = -ENOMEM;
-               goto err_eswitch;
+               goto err_npars;
        }
 
        ret = qlcnic_get_pci_info(adapter, pci_info);
-       if (!ret) {
-               for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-                       pfn = pci_info[i].id;
-                       if (pfn > QLCNIC_MAX_PCI_FUNC)
-                               return QL_STATUS_INVALID_PARAM;
-                       adapter->npars[pfn].active = pci_info[i].active;
-                       adapter->npars[pfn].type = pci_info[i].type;
-                       adapter->npars[pfn].phy_port = pci_info[i].default_port;
-                       adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
-                       adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
-                       adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
-               }
-
-               for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
-                       adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
+       if (ret)
+               goto err_eswitch;
 
-               return ret;
+       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+               pfn = pci_info[i].id;
+               if (pfn > QLCNIC_MAX_PCI_FUNC)
+                       return QL_STATUS_INVALID_PARAM;
+               adapter->npars[pfn].active = pci_info[i].active;
+               adapter->npars[pfn].type = pci_info[i].type;
+               adapter->npars[pfn].phy_port = pci_info[i].default_port;
+               adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+               adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
+               adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
        }
 
+       for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
+               adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
+
+       kfree(pci_info);
+       return 0;
+
+err_eswitch:
        kfree(adapter->eswitch);
        adapter->eswitch = NULL;
-err_eswitch:
+err_npars:
        kfree(adapter->npars);
+       adapter->npars = NULL;
+err_pci_info:
+       kfree(pci_info);
 
        return ret;
 }
@@ -3361,15 +3371,21 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
        struct device *dev = container_of(kobj, struct device, kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
-       struct qlcnic_pci_info  pci_info[QLCNIC_MAX_PCI_FUNC];
+       struct qlcnic_pci_info *pci_info;
        int i, ret;
 
        if (size != sizeof(pci_cfg))
                return QL_STATUS_INVALID_PARAM;
 
+       pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+       if (!pci_info)
+               return -ENOMEM;
+
        ret = qlcnic_get_pci_info(adapter, pci_info);
-       if (ret)
+       if (ret) {
+               kfree(pci_info);
                return ret;
+       }
 
        for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
                pci_cfg[i].pci_func = pci_info[i].id;
@@ -3380,8 +3396,8 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
                memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
        }
        memcpy(buf, &pci_cfg, size);
+       kfree(pci_info);
        return size;
-
 }
 static struct bin_attribute bin_attr_npar_config = {
        .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
index 7f62e2dea28f7423bd7539253e5698ab2094f049..ca7fc9df1ccf900533d56c35326b360316283af2 100644 (file)
@@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
 
 static void rx_complete (struct urb *urb);
 
-static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
+static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
 {
        struct sk_buff          *skb;
        struct skb_data         *entry;
@@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
                netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
                usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
                usb_free_urb (urb);
-               return;
+               return -ENOMEM;
        }
        skb_reserve (skb, NET_IP_ALIGN);
 
@@ -357,6 +357,9 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
                        netif_dbg(dev, ifdown, dev->net, "device gone\n");
                        netif_device_detach (dev->net);
                        break;
+               case -EHOSTUNREACH:
+                       retval = -ENOLINK;
+                       break;
                default:
                        netif_dbg(dev, rx_err, dev->net,
                                  "rx submit, %d\n", retval);
@@ -374,6 +377,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
                dev_kfree_skb_any (skb);
                usb_free_urb (urb);
        }
+       return retval;
 }
 
 
@@ -912,6 +916,7 @@ fail_halt:
        /* tasklet could resubmit itself forever if memory is tight */
        if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {
                struct urb      *urb = NULL;
+               int resched = 1;
 
                if (netif_running (dev->net))
                        urb = usb_alloc_urb (0, GFP_KERNEL);
@@ -922,10 +927,12 @@ fail_halt:
                        status = usb_autopm_get_interface(dev->intf);
                        if (status < 0)
                                goto fail_lowmem;
-                       rx_submit (dev, urb, GFP_KERNEL);
+                       if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK)
+                               resched = 0;
                        usb_autopm_put_interface(dev->intf);
 fail_lowmem:
-                       tasklet_schedule (&dev->bh);
+                       if (resched)
+                               tasklet_schedule (&dev->bh);
                }
        }
 
@@ -1175,8 +1182,11 @@ static void usbnet_bh (unsigned long param)
                        // don't refill the queue all at once
                        for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
                                urb = usb_alloc_urb (0, GFP_ATOMIC);
-                               if (urb != NULL)
-                                       rx_submit (dev, urb, GFP_ATOMIC);
+                               if (urb != NULL) {
+                                       if (rx_submit (dev, urb, GFP_ATOMIC) ==
+                                           -ENOLINK)
+                                               return;
+                               }
                        }
                        if (temp != dev->rxq.qlen)
                                netif_dbg(dev, link, dev->net,
index ad7719fe6d0a2ced65c2db0a27faeeab6550486a..e050bd65e0378cbdd6643d893c01a4462a2dea2f 100644 (file)
@@ -885,20 +885,21 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
  *      Receive a frame through the DMA
  */
 static inline void
-fst_rx_dma(struct fst_card_info *card, unsigned char *skb,
-          unsigned char *mem, int len)
+fst_rx_dma(struct fst_card_info *card, dma_addr_t skb,
+          dma_addr_t mem, int len)
 {
        /*
         * This routine will setup the DMA and start it
         */
 
-       dbg(DBG_RX, "In fst_rx_dma %p %p %d\n", skb, mem, len);
+       dbg(DBG_RX, "In fst_rx_dma %lx %lx %d\n",
+           (unsigned long) skb, (unsigned long) mem, len);
        if (card->dmarx_in_progress) {
                dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n");
        }
 
-       outl((unsigned long) skb, card->pci_conf + DMAPADR0);   /* Copy to here */
-       outl((unsigned long) mem, card->pci_conf + DMALADR0);   /* from here */
+       outl(skb, card->pci_conf + DMAPADR0);   /* Copy to here */
+       outl(mem, card->pci_conf + DMALADR0);   /* from here */
        outl(len, card->pci_conf + DMASIZ0);    /* for this length */
        outl(0x00000000c, card->pci_conf + DMADPR0);    /* In this direction */
 
@@ -1309,8 +1310,8 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port)
                card->dma_port_rx = port;
                card->dma_len_rx = len;
                card->dma_rxpos = rxp;
-               fst_rx_dma(card, (char *) card->rx_dma_handle_card,
-                          (char *) BUF_OFFSET(rxBuffer[pi][rxp][0]), len);
+               fst_rx_dma(card, card->rx_dma_handle_card,
+                          BUF_OFFSET(rxBuffer[pi][rxp][0]), len);
        }
        if (rxp != port->rxpos) {
                dbg(DBG_ASS, "About to increment rxpos by more than 1\n");
index 8848333bc3a9545e8ed6a9dd3d8905bfeee6e33f..fec026212326dce857220196dd312c3b2d5b6c69 100644 (file)
@@ -260,7 +260,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
        .shadow_ram_support = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
index a07310fefcf2d0e56c45d45fabce4251d26e12fc..6950a783913b83561839f20a08657857ee242a86 100644 (file)
@@ -769,22 +769,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
                rts_retry_limit = data_retry_limit;
        tx_cmd->rts_retry_limit = rts_retry_limit;
 
-       if (ieee80211_is_mgmt(fc)) {
-               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-               case cpu_to_le16(IEEE80211_STYPE_AUTH):
-               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-                       if (tx_flags & TX_CMD_FLG_RTS_MSK) {
-                               tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-                               tx_flags |= TX_CMD_FLG_CTS_MSK;
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }
-
        tx_cmd->rate = rate;
        tx_cmd->tx_flags = tx_flags;
 
@@ -2717,7 +2701,7 @@ static struct iwl_lib_ops iwl3945_lib = {
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
        .get_hcmd_size = iwl3945_get_hcmd_size,
        .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-       .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+       .tx_cmd_protection = iwlcore_tx_cmd_protection,
        .request_scan = iwl3945_request_scan,
 };
 
index d6531ad3906a5d2a407ff2c5c106a6cf335ead10..d6da356608fa46efe34a317bdda60c6680b65d7e 100644 (file)
@@ -2223,7 +2223,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
        .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
        .chain_noise_reset = iwl4965_chain_noise_reset,
        .gain_computation = iwl4965_gain_computation,
-       .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+       .tx_cmd_protection = iwlcore_tx_cmd_protection,
        .calc_rssi = iwl4965_calc_rssi,
        .request_scan = iwlagn_request_scan,
 };
index 8093ce2804fb31d3fb5e00cbc7f49da19d9543b6..aacf3770f075b4abd1de4a474f79cc60eb42c9cc 100644 (file)
@@ -506,7 +506,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
@@ -537,7 +537,7 @@ struct iwl_cfg iwl5100_bgn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
@@ -597,7 +597,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
@@ -628,7 +628,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
@@ -659,7 +659,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
index 58270529a0e4efc4ea3198ce9aa27fc45d1c9707..af4fd50f3405db334ce2e44e1ce648c7c510ed7c 100644 (file)
@@ -381,7 +381,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -489,7 +489,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -563,7 +563,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -637,7 +637,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -714,7 +714,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -821,7 +821,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -859,7 +859,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
@@ -933,7 +933,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
index a7216dda97868dd576c02ddee55484e9a3121ac4..75b901b3eb1ebff8cb5a7adbbd380db5cd8bc88f 100644 (file)
@@ -211,10 +211,21 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
        }
 }
 
-static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
-                       __le32 *tx_flags)
+static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
+                                    struct ieee80211_tx_info *info,
+                                    __le16 fc, __le32 *tx_flags)
 {
-       *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
+           info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+               *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+               return;
+       }
+
+       if (priv->cfg->use_rts_for_aggregation &&
+           info->flags & IEEE80211_TX_CTL_AMPDU) {
+               *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+               return;
+       }
 }
 
 /* Calc max signal level (dBm) among 3 possible receivers */
@@ -268,7 +279,7 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
        .build_addsta_hcmd = iwlagn_build_addsta_hcmd,
        .gain_computation = iwlagn_gain_computation,
        .chain_noise_reset = iwlagn_chain_noise_reset,
-       .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag,
+       .tx_cmd_protection = iwlagn_tx_cmd_protection,
        .calc_rssi = iwlagn_calc_rssi,
        .request_scan = iwlagn_request_scan,
 };
index d04502d54df3c48b0d869c5169bf79ee397ecf1e..69155aa448fb80f8c042b212567679b905e20513 100644 (file)
@@ -379,10 +379,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
        }
 
-       priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
-
-       if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
-               tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+       priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
 
        tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
        if (ieee80211_is_mgmt(fc)) {
@@ -456,21 +453,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
        if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
                rate_flags |= RATE_MCS_CCK_MSK;
 
-       /* Set up RTS and CTS flags for certain packets */
-       switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-       case cpu_to_le16(IEEE80211_STYPE_AUTH):
-       case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-       case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-       case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-               if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) {
-                       tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-                       tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK;
-               }
-               break;
-       default:
-               break;
-       }
-
        /* Set up antennas */
        priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
                                              priv->hw_params.valid_tx_ant);
index 35337b1e7caceeac3b14ee0c4a2ea3a660010989..c1882fd8345d43dd630718c1f9475533511e5f7c 100644 (file)
@@ -202,13 +202,6 @@ int iwl_commit_rxon(struct iwl_priv *priv)
 
        priv->start_calib = 0;
        if (new_assoc) {
-               /*
-                * allow CTS-to-self if possible for new association.
-                * this is relevant only for 5000 series and up,
-                * but will not damage 4965
-                */
-               priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
-
                /* Apply the new configuration
                 * RXON assoc doesn't clear the station table in uCode,
                 */
@@ -1618,45 +1611,9 @@ static ssize_t store_tx_power(struct device *d,
 
 static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
 
-static ssize_t show_rts_ht_protection(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       return sprintf(buf, "%s\n",
-               priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
-}
-
-static ssize_t store_rts_ht_protection(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "Input is not in decimal form.\n");
-       else {
-               if (!iwl_is_associated(priv))
-                       priv->cfg->use_rts_for_ht = val ? true : false;
-               else
-                       IWL_ERR(priv, "Sta associated with AP - "
-                               "Change protection mechanism is not allowed\n");
-               ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
-                       show_rts_ht_protection, store_rts_ht_protection);
-
-
 static struct attribute *iwl_sysfs_entries[] = {
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
-       &dev_attr_rts_ht_protection.attr,
 #ifdef CONFIG_IWLWIFI_DEBUG
        &dev_attr_debug_level.attr,
 #endif
@@ -3464,25 +3421,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
-/*
- * switch to RTS/CTS for TX
- */
-static void iwl_enable_rts_cts(struct iwl_priv *priv)
-{
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
-       if (!test_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_INFO(priv, "use RTS/CTS protection\n");
-               iwlcore_commit_rxon(priv);
-       } else {
-               /* scanning, defer the request until scan completed */
-               IWL_DEBUG_INFO(priv, "defer setting RTS/CTS protection\n");
-       }
-}
-
 static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
                                struct ieee80211_vif *vif,
                                enum ieee80211_ampdu_mlme_action action,
@@ -3529,14 +3467,33 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                        ret = 0;
+               if (priv->cfg->use_rts_for_aggregation) {
+                       struct iwl_station_priv *sta_priv =
+                               (void *) sta->drv_priv;
+                       /*
+                        * switch off RTS/CTS if it was previously enabled
+                        */
+
+                       sta_priv->lq_sta.lq.general_params.flags &=
+                               ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
+                       iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
+                               CMD_ASYNC, false);
+               }
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
-               if (priv->cfg->use_rts_for_ht) {
+               if (priv->cfg->use_rts_for_aggregation) {
+                       struct iwl_station_priv *sta_priv =
+                               (void *) sta->drv_priv;
+
                        /*
                         * switch to RTS/CTS if it is the prefer protection
                         * method for HT traffic
                         */
-                       iwl_enable_rts_cts(priv);
+
+                       sta_priv->lq_sta.lq.general_params.flags |=
+                               LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
+                       iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
+                               CMD_ASYNC, false);
                }
                ret = 0;
                break;
index 8ccb6d205b6d6219c5e23c38806113f8514ef3ac..2c03c6e20a72d73ded70f8c96d37bfce6aa8e263 100644 (file)
@@ -401,21 +401,38 @@ void iwlcore_free_geos(struct iwl_priv *priv)
 EXPORT_SYMBOL(iwlcore_free_geos);
 
 /*
- *  iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this
+ *  iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
  *  function.
  */
-void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
-                               __le32 *tx_flags)
+void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
+                              struct ieee80211_tx_info *info,
+                              __le16 fc, __le32 *tx_flags)
 {
        if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
                *tx_flags |= TX_CMD_FLG_RTS_MSK;
                *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+               if (!ieee80211_is_mgmt(fc))
+                       return;
+
+               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+               case cpu_to_le16(IEEE80211_STYPE_AUTH):
+               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+                       *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+                       *tx_flags |= TX_CMD_FLG_CTS_MSK;
+                       break;
+               }
        } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
                *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
                *tx_flags |= TX_CMD_FLG_CTS_MSK;
+               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
        }
 }
-EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag);
+EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
+
 
 static bool is_single_rx_stream(struct iwl_priv *priv)
 {
@@ -1869,6 +1886,10 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
                        priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
                else
                        priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+               if (bss_conf->use_cts_prot)
+                       priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
+               else
+                       priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
        }
 
        if (changes & BSS_CHANGED_BASIC_RATES) {
index e9d23f2f869d8c72a81c00b4890e215518e058ff..4a71dfb10a15d0f6ebf4007944d011d249333902 100644 (file)
@@ -104,8 +104,9 @@ struct iwl_hcmd_utils_ops {
                        u32 min_average_noise,
                        u8 default_chain);
        void (*chain_noise_reset)(struct iwl_priv *priv);
-       void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info,
-                       __le32 *tx_flags);
+       void (*tx_cmd_protection)(struct iwl_priv *priv,
+                                 struct ieee80211_tx_info *info,
+                                 __le16 fc, __le32 *tx_flags);
        int  (*calc_rssi)(struct iwl_priv *priv,
                          struct iwl_rx_phy_res *rx_resp);
        void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
@@ -249,7 +250,7 @@ struct iwl_mod_params {
  * @led_compensation: compensate on the led on/off time per HW according
  *     to the deviation to achieve the desired led frequency.
  *     The detail algorithm is described in iwl-led.c
- * @use_rts_for_ht: use rts/cts protection for HT traffic
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
  * @chain_noise_num_beacons: number of beacons used to compute chain noise
  * @adv_thermal_throttle: support advance thermal throttle
  * @support_ct_kill_exit: support ct kill exit condition
@@ -318,7 +319,7 @@ struct iwl_cfg {
        const bool ht_greenfield_support;
        u16 led_compensation;
        const bool broken_powersave;
-       bool use_rts_for_ht;
+       bool use_rts_for_aggregation;
        int chain_noise_num_beacons;
        const bool supports_idle;
        bool adv_thermal_throttle;
@@ -390,8 +391,9 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
 int iwl_alloc_txq_mem(struct iwl_priv *priv);
 void iwl_free_txq_mem(struct iwl_priv *priv);
-void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
-                               __le32 *tx_flags);
+void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
+                              struct ieee80211_tx_info *info,
+                              __le16 fc, __le32 *tx_flags);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
index d24eb47d370548b73036411c3532443e2d149c28..70c4b8fba0ee89093c56c056e7152b927da5a37c 100644 (file)
@@ -435,10 +435,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
        }
 
-       priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
-
-       if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
-               tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+       priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
 
        tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
        if (ieee80211_is_mgmt(fc)) {
index 2372abb29c2e1e1a56050cf4a1a07001ab6fbdfd..3e82f162720972d8c6bd732fa437c7fc7046bde6 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 #include <asm/unaligned.h>
index 71a101fb2e4ecad6639d9e878fcdac3e68224f34..822f8dc26e9c051d3b9ee34e79ef715b0f204067 100644 (file)
@@ -43,8 +43,6 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        { PCI_DEVICE(0x1260, 0x3886) },
        /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
        { PCI_DEVICE(0x1260, 0xffff) },
-       /* Standard Microsystems Corp SMC2802W Wireless PCI */
-       { PCI_DEVICE(0x10b8, 0x2802) },
        { },
 };
 
index 1a84fae155e1b2890652b916eebb65c7ea7dfee0..8373ca0de8e0b00484f40d48c5813e600da920c2 100644 (file)
@@ -1325,14 +1325,14 @@ static void __dasd_device_check_expire(struct dasd_device *device)
                if (device->discipline->term_IO(cqr) != 0) {
                        /* Hmpf, try again in 5 sec */
                        dev_err(&device->cdev->dev,
-                               "cqr %p timed out (%is) but cannot be "
+                               "cqr %p timed out (%lus) but cannot be "
                                "ended, retrying in 5 s\n",
                                cqr, (cqr->expires/HZ));
                        cqr->expires += 5*HZ;
                        dasd_device_set_timer(device, 5*HZ);
                } else {
                        dev_err(&device->cdev->dev,
-                               "cqr %p timed out (%is), %i retries "
+                               "cqr %p timed out (%lus), %i retries "
                                "remaining\n", cqr, (cqr->expires/HZ),
                                cqr->retries);
                }
index a75ed3083a6ae266d66b9630140b42db8d07266e..8e4153d740f3bf00d4a465bf5a1526ee66ad518e 100644 (file)
@@ -386,7 +386,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
         struct chbk *p_ch;
 
        CLAW_DBF_TEXT(4, trace, "claw_tx");
-        p_ch=&privptr->channel[WRITE];
+       p_ch = &privptr->channel[WRITE_CHANNEL];
         spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
         rc=claw_hw_tx( skb, dev, 1 );
         spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
@@ -407,7 +407,7 @@ static struct sk_buff *
 claw_pack_skb(struct claw_privbk *privptr)
 {
        struct sk_buff *new_skb,*held_skb;
-       struct chbk *p_ch = &privptr->channel[WRITE];
+       struct chbk *p_ch = &privptr->channel[WRITE_CHANNEL];
        struct claw_env  *p_env = privptr->p_env;
        int     pkt_cnt,pk_ind,so_far;
 
@@ -515,15 +515,15 @@ claw_open(struct net_device *dev)
                privptr->p_env->write_size=CLAW_FRAME_SIZE;
        }
         claw_set_busy(dev);
-       tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet,
-               (unsigned long) &privptr->channel[READ]);
+       tasklet_init(&privptr->channel[READ_CHANNEL].tasklet, claw_irq_tasklet,
+               (unsigned long) &privptr->channel[READ_CHANNEL]);
         for ( i = 0; i < 2;  i++) {
                CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i);
                 init_waitqueue_head(&privptr->channel[i].wait);
                /* skb_queue_head_init(&p_ch->io_queue); */
-               if (i == WRITE)
+               if (i == WRITE_CHANNEL)
                        skb_queue_head_init(
-                               &privptr->channel[WRITE].collect_queue);
+                               &privptr->channel[WRITE_CHANNEL].collect_queue);
                 privptr->channel[i].flag_a = 0;
                 privptr->channel[i].IO_active = 0;
                 privptr->channel[i].flag  &= ~CLAW_TIMER;
@@ -551,12 +551,12 @@ claw_open(struct net_device *dev)
                 if((privptr->channel[i].flag & CLAW_TIMER) == 0x00)
                         del_timer(&timer);
         }
-        if ((((privptr->channel[READ].last_dstat |
-               privptr->channel[WRITE].last_dstat) &
+       if ((((privptr->channel[READ_CHANNEL].last_dstat |
+               privptr->channel[WRITE_CHANNEL].last_dstat) &
            ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
-           (((privptr->channel[READ].flag |
-               privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
-               dev_info(&privptr->channel[READ].cdev->dev,
+          (((privptr->channel[READ_CHANNEL].flag |
+               privptr->channel[WRITE_CHANNEL].flag) & CLAW_TIMER) != 0x00)) {
+               dev_info(&privptr->channel[READ_CHANNEL].cdev->dev,
                        "%s: remote side is not ready\n", dev->name);
                CLAW_DBF_TEXT(2, trace, "notrdy");
 
@@ -608,8 +608,8 @@ claw_open(struct net_device *dev)
                         }
                 }
                privptr->buffs_alloc = 0;
-               privptr->channel[READ].flag= 0x00;
-               privptr->channel[WRITE].flag = 0x00;
+               privptr->channel[READ_CHANNEL].flag = 0x00;
+               privptr->channel[WRITE_CHANNEL].flag = 0x00;
                 privptr->p_buff_ccw=NULL;
                 privptr->p_buff_read=NULL;
                 privptr->p_buff_write=NULL;
@@ -652,10 +652,10 @@ claw_irq_handler(struct ccw_device *cdev,
         }
 
        /* Try to extract channel from driver data. */
-       if (privptr->channel[READ].cdev == cdev)
-               p_ch = &privptr->channel[READ];
-       else if (privptr->channel[WRITE].cdev == cdev)
-               p_ch = &privptr->channel[WRITE];
+       if (privptr->channel[READ_CHANNEL].cdev == cdev)
+               p_ch = &privptr->channel[READ_CHANNEL];
+       else if (privptr->channel[WRITE_CHANNEL].cdev == cdev)
+               p_ch = &privptr->channel[WRITE_CHANNEL];
        else {
                dev_warn(&cdev->dev, "The device is not a CLAW device\n");
                CLAW_DBF_TEXT(2, trace, "badchan");
@@ -813,7 +813,7 @@ claw_irq_handler(struct ccw_device *cdev,
                        claw_clearbit_busy(TB_TX, dev);
                        claw_clear_busy(dev);
                }
-               p_ch_r = (struct chbk *)&privptr->channel[READ];
+               p_ch_r = (struct chbk *)&privptr->channel[READ_CHANNEL];
                if (test_and_set_bit(CLAW_BH_ACTIVE,
                        (void *)&p_ch_r->flag_a) == 0)
                        tasklet_schedule(&p_ch_r->tasklet);
@@ -878,13 +878,13 @@ claw_release(struct net_device *dev)
         for ( i = 1; i >=0 ;  i--) {
                 spin_lock_irqsave(
                        get_ccwdev_lock(privptr->channel[i].cdev), saveflags);
-             /*   del_timer(&privptr->channel[READ].timer);  */
+            /*   del_timer(&privptr->channel[READ_CHANNEL].timer);  */
                privptr->channel[i].claw_state = CLAW_STOP;
                 privptr->channel[i].IO_active = 0;
                 parm = (unsigned long) &privptr->channel[i];
-               if (i == WRITE)
+               if (i == WRITE_CHANNEL)
                        claw_purge_skb_queue(
-                               &privptr->channel[WRITE].collect_queue);
+                               &privptr->channel[WRITE_CHANNEL].collect_queue);
                 rc = ccw_device_halt (privptr->channel[i].cdev, parm);
                if (privptr->system_validate_comp==0x00)  /* never opened? */
                    init_waitqueue_head(&privptr->channel[i].wait);
@@ -971,16 +971,16 @@ claw_release(struct net_device *dev)
         privptr->mtc_skipping = 1;
         privptr->mtc_offset=0;
 
-        if (((privptr->channel[READ].last_dstat |
-               privptr->channel[WRITE].last_dstat) &
+       if (((privptr->channel[READ_CHANNEL].last_dstat |
+               privptr->channel[WRITE_CHANNEL].last_dstat) &
                ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) {
-               dev_warn(&privptr->channel[READ].cdev->dev,
+               dev_warn(&privptr->channel[READ_CHANNEL].cdev->dev,
                        "Deactivating %s completed with incorrect"
                        " subchannel status "
                        "(read %02x, write %02x)\n",
                 dev->name,
-               privptr->channel[READ].last_dstat,
-               privptr->channel[WRITE].last_dstat);
+               privptr->channel[READ_CHANNEL].last_dstat,
+               privptr->channel[WRITE_CHANNEL].last_dstat);
                 CLAW_DBF_TEXT(2, trace, "badclose");
         }
        CLAW_DBF_TEXT(4, trace, "rlsexit");
@@ -1324,7 +1324,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
 
        CLAW_DBF_TEXT(4, trace, "hw_tx");
        privptr = (struct claw_privbk *)(dev->ml_priv);
-        p_ch=(struct chbk *)&privptr->channel[WRITE];
+       p_ch = (struct chbk *)&privptr->channel[WRITE_CHANNEL];
        p_env =privptr->p_env;
        claw_free_wrt_buf(dev); /* Clean up free chain if posible */
         /*  scan the write queue to free any completed write packets   */
@@ -1357,7 +1357,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
                                 claw_strt_out_IO(dev );
                                 claw_free_wrt_buf( dev );
                                 if (privptr->write_free_count==0) {
-                                       ch = &privptr->channel[WRITE];
+                                       ch = &privptr->channel[WRITE_CHANNEL];
                                        atomic_inc(&skb->users);
                                        skb_queue_tail(&ch->collect_queue, skb);
                                        goto Done;
@@ -1369,7 +1369,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
                 }
                 /*  tx lock  */
                 if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */
-                       ch = &privptr->channel[WRITE];
+                       ch = &privptr->channel[WRITE_CHANNEL];
                        atomic_inc(&skb->users);
                        skb_queue_tail(&ch->collect_queue, skb);
                         claw_strt_out_IO(dev );
@@ -1385,7 +1385,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
             privptr->p_write_free_chain == NULL ) {
 
                 claw_setbit_busy(TB_NOBUFFER,dev);
-               ch = &privptr->channel[WRITE];
+               ch = &privptr->channel[WRITE_CHANNEL];
                atomic_inc(&skb->users);
                skb_queue_tail(&ch->collect_queue, skb);
                CLAW_DBF_TEXT(2, trace, "clawbusy");
@@ -1397,7 +1397,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
         while (len_of_data > 0) {
                 p_this_ccw=privptr->p_write_free_chain;  /* get a block */
                if (p_this_ccw == NULL) { /* lost the race */
-                       ch = &privptr->channel[WRITE];
+                       ch = &privptr->channel[WRITE_CHANNEL];
                        atomic_inc(&skb->users);
                        skb_queue_tail(&ch->collect_queue, skb);
                        goto Done2;
@@ -2067,7 +2067,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        *catch up to each other */
        privptr = dev->ml_priv;
         p_env=privptr->p_env;
-       tdev = &privptr->channel[READ].cdev->dev;
+       tdev = &privptr->channel[READ_CHANNEL].cdev->dev;
        memcpy( &temp_host_name, p_env->host_name, 8);
         memcpy( &temp_ws_name, p_env->adapter_name , 8);
        dev_info(tdev, "%s: CLAW device %.8s: "
@@ -2245,7 +2245,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        dev->name, temp_ws_name,
                        p_ctlbk->linkid);
                        privptr->active_link_ID = p_ctlbk->linkid;
-                       p_ch = &privptr->channel[WRITE];
+                       p_ch = &privptr->channel[WRITE_CHANNEL];
                        wake_up(&p_ch->wait);  /* wake up claw_open ( WRITE) */
                break;
        case CONNECTION_RESPONSE:
@@ -2296,7 +2296,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                                "%s: Confirmed Now packing\n", dev->name);
                                p_env->packing = DO_PACKED;
                        }
-                       p_ch = &privptr->channel[WRITE];
+                       p_ch = &privptr->channel[WRITE_CHANNEL];
                        wake_up(&p_ch->wait);
                } else {
                        dev_warn(tdev, "Activating %s failed because of"
@@ -2556,7 +2556,7 @@ unpack_read(struct net_device *dev )
        p_packd=NULL;
        privptr = dev->ml_priv;
 
-       p_dev = &privptr->channel[READ].cdev->dev;
+       p_dev = &privptr->channel[READ_CHANNEL].cdev->dev;
        p_env = privptr->p_env;
         p_this_ccw=privptr->p_read_active_first;
        while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) {
@@ -2728,7 +2728,7 @@ claw_strt_read (struct net_device *dev, int lock )
         struct ccwbk*p_ccwbk;
         struct chbk *p_ch;
         struct clawh *p_clawh;
-        p_ch=&privptr->channel[READ];
+       p_ch = &privptr->channel[READ_CHANNEL];
 
        CLAW_DBF_TEXT(4, trace, "StRdNter");
         p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
@@ -2782,7 +2782,7 @@ claw_strt_out_IO( struct net_device *dev )
                return;
        }
        privptr = (struct claw_privbk *)dev->ml_priv;
-        p_ch=&privptr->channel[WRITE];
+       p_ch = &privptr->channel[WRITE_CHANNEL];
 
        CLAW_DBF_TEXT(4, trace, "strt_io");
         p_first_ccw=privptr->p_write_active_first;
@@ -2875,7 +2875,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
        if (dev->flags & IFF_RUNNING)
                claw_release(dev);
        if (privptr) {
-               privptr->channel[READ].ndev = NULL;  /* say it's free */
+               privptr->channel[READ_CHANNEL].ndev = NULL;  /* say it's free */
        }
        dev->ml_priv = NULL;
 #ifdef MODULE
@@ -2960,18 +2960,18 @@ claw_new_device(struct ccwgroup_device *cgdev)
        struct ccw_dev_id dev_id;
 
        dev_info(&cgdev->dev, "add for %s\n",
-                dev_name(&cgdev->cdev[READ]->dev));
+                dev_name(&cgdev->cdev[READ_CHANNEL]->dev));
        CLAW_DBF_TEXT(2, setup, "new_dev");
        privptr = dev_get_drvdata(&cgdev->dev);
-       dev_set_drvdata(&cgdev->cdev[READ]->dev, privptr);
-       dev_set_drvdata(&cgdev->cdev[WRITE]->dev, privptr);
+       dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, privptr);
+       dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, privptr);
        if (!privptr)
                return -ENODEV;
        p_env = privptr->p_env;
-       ccw_device_get_id(cgdev->cdev[READ], &dev_id);
-       p_env->devno[READ] = dev_id.devno;
-       ccw_device_get_id(cgdev->cdev[WRITE], &dev_id);
-       p_env->devno[WRITE] = dev_id.devno;
+       ccw_device_get_id(cgdev->cdev[READ_CHANNEL], &dev_id);
+       p_env->devno[READ_CHANNEL] = dev_id.devno;
+       ccw_device_get_id(cgdev->cdev[WRITE_CHANNEL], &dev_id);
+       p_env->devno[WRITE_CHANNEL] = dev_id.devno;
        ret = add_channel(cgdev->cdev[0],0,privptr);
        if (ret == 0)
                ret = add_channel(cgdev->cdev[1],1,privptr);
@@ -2980,14 +2980,14 @@ claw_new_device(struct ccwgroup_device *cgdev)
                        " failed with error code %d\n", ret);
                goto out;
        }
-       ret = ccw_device_set_online(cgdev->cdev[READ]);
+       ret = ccw_device_set_online(cgdev->cdev[READ_CHANNEL]);
        if (ret != 0) {
                dev_warn(&cgdev->dev,
                        "Setting the read subchannel online"
                        " failed with error code %d\n", ret);
                goto out;
        }
-       ret = ccw_device_set_online(cgdev->cdev[WRITE]);
+       ret = ccw_device_set_online(cgdev->cdev[WRITE_CHANNEL]);
        if (ret != 0) {
                dev_warn(&cgdev->dev,
                        "Setting the write subchannel online "
@@ -3002,8 +3002,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
        }
        dev->ml_priv = privptr;
        dev_set_drvdata(&cgdev->dev, privptr);
-       dev_set_drvdata(&cgdev->cdev[READ]->dev, privptr);
-       dev_set_drvdata(&cgdev->cdev[WRITE]->dev, privptr);
+       dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, privptr);
+       dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, privptr);
        /* sysfs magic */
         SET_NETDEV_DEV(dev, &cgdev->dev);
        if (register_netdev(dev) != 0) {
@@ -3021,16 +3021,16 @@ claw_new_device(struct ccwgroup_device *cgdev)
                        goto out;
                }
        }
-       privptr->channel[READ].ndev = dev;
-       privptr->channel[WRITE].ndev = dev;
+       privptr->channel[READ_CHANNEL].ndev = dev;
+       privptr->channel[WRITE_CHANNEL].ndev = dev;
        privptr->p_env->ndev = dev;
 
        dev_info(&cgdev->dev, "%s:readsize=%d  writesize=%d "
                "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n",
                 dev->name, p_env->read_size,
                p_env->write_size, p_env->read_buffers,
-                p_env->write_buffers, p_env->devno[READ],
-               p_env->devno[WRITE]);
+               p_env->write_buffers, p_env->devno[READ_CHANNEL],
+               p_env->devno[WRITE_CHANNEL]);
        dev_info(&cgdev->dev, "%s:host_name:%.8s, adapter_name "
                ":%.8s api_type: %.8s\n",
                 dev->name, p_env->host_name,
@@ -3072,10 +3072,10 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
        priv = dev_get_drvdata(&cgdev->dev);
        if (!priv)
                return -ENODEV;
-       ndev = priv->channel[READ].ndev;
+       ndev = priv->channel[READ_CHANNEL].ndev;
        if (ndev) {
                /* Close the device */
-               dev_info(&cgdev->dev, "%s: shutting down \n",
+               dev_info(&cgdev->dev, "%s: shutting down\n",
                        ndev->name);
                if (ndev->flags & IFF_RUNNING)
                        ret = claw_release(ndev);
@@ -3083,8 +3083,8 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
                unregister_netdev(ndev);
                ndev->ml_priv = NULL;  /* cgdev data, not ndev's to free */
                claw_free_netdevice(ndev, 1);
-               priv->channel[READ].ndev = NULL;
-               priv->channel[WRITE].ndev = NULL;
+               priv->channel[READ_CHANNEL].ndev = NULL;
+               priv->channel[WRITE_CHANNEL].ndev = NULL;
                priv->p_env->ndev = NULL;
        }
        ccw_device_set_offline(cgdev->cdev[1]);
@@ -3115,8 +3115,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
        priv->channel[1].irb=NULL;
        kfree(priv);
        dev_set_drvdata(&cgdev->dev, NULL);
-       dev_set_drvdata(&cgdev->cdev[READ]->dev, NULL);
-       dev_set_drvdata(&cgdev->cdev[WRITE]->dev, NULL);
+       dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, NULL);
+       dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, NULL);
        put_device(&cgdev->dev);
 
        return;
index 46d59a13db12d1aabdaf87d497dbe2f3d1c02d55..1bc5904df19ff550d3094ed939faab28f5cac44c 100644 (file)
@@ -74,8 +74,8 @@
 #define MAX_ENVELOPE_SIZE       65536
 #define CLAW_DEFAULT_MTU_SIZE   4096
 #define DEF_PACK_BUFSIZE       32768
-#define READ                    0
-#define WRITE                   1
+#define READ_CHANNEL           0
+#define WRITE_CHANNEL          1
 
 #define TB_TX                   0          /* sk buffer handling in process  */
 #define TB_STOP                 1          /* network device stop in process */
index 70eb7f1384146e4138e5853534a87966cf79fb5a..8c921fc3511a5e741b187e9f32e763f004b11427 100644 (file)
@@ -454,7 +454,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg)
        if ((fsmstate == CTC_STATE_SETUPWAIT) &&
            (ch->protocol == CTCM_PROTO_OS390)) {
                /* OS/390 resp. z/OS */
-               if (CHANNEL_DIRECTION(ch->flags) == READ) {
+               if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {
                        *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
                        fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC,
                                     CTC_EVENT_TIMER, ch);
@@ -472,14 +472,14 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg)
         * if in compatibility mode, since VM TCP delays the initial
         * frame until it has some data to send.
         */
-       if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
+       if ((CHANNEL_DIRECTION(ch->flags) == CTCM_WRITE) ||
            (ch->protocol != CTCM_PROTO_S390))
                fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
 
        *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
        ch->ccw[1].count = 2;   /* Transfer only length */
 
-       fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+       fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)
                     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
        rc = ccw_device_start(ch->cdev, &ch->ccw[0],
                                        (unsigned long)ch, 0xff, 0);
@@ -495,7 +495,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg)
         * reply from VM TCP which brings up the RX channel to it's
         * final state.
         */
-       if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
+       if ((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) &&
            (ch->protocol == CTCM_PROTO_S390)) {
                struct net_device *dev = ch->netdev;
                struct ctcm_priv *priv = dev->ml_priv;
@@ -600,15 +600,15 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
        int rc;
 
        CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s",
-                       CTCM_FUNTAIL, ch->id,
-                       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+               CTCM_FUNTAIL, ch->id,
+               (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX");
 
        if (ch->trans_skb != NULL) {
                clear_normalized_cda(&ch->ccw[1]);
                dev_kfree_skb(ch->trans_skb);
                ch->trans_skb = NULL;
        }
-       if (CHANNEL_DIRECTION(ch->flags) == READ) {
+       if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {
                ch->ccw[1].cmd_code = CCW_CMD_READ;
                ch->ccw[1].flags = CCW_FLAG_SLI;
                ch->ccw[1].count = 0;
@@ -622,7 +622,8 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
                        "%s(%s): %s trans_skb alloc delayed "
                        "until first transfer",
                        CTCM_FUNTAIL, ch->id,
-                       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+                       (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?
+                               "RX" : "TX");
        }
        ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
        ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
@@ -720,7 +721,7 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state,
 
        ch->th_seg = 0x00;
        ch->th_seq_num = 0x00;
-       if (CHANNEL_DIRECTION(ch->flags) == READ) {
+       if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {
                skb_queue_purge(&ch->io_queue);
                fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
        } else {
@@ -799,7 +800,8 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
                fsm_newstate(fi, CTC_STATE_STARTRETRY);
                fsm_deltimer(&ch->timer);
                fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
-               if (!IS_MPC(ch) && (CHANNEL_DIRECTION(ch->flags) == READ)) {
+               if (!IS_MPC(ch) &&
+                   (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)) {
                        int rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
                        if (rc != 0)
                                ctcm_ccw_check_rc(ch, rc,
@@ -811,10 +813,10 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
        CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
                "%s(%s) : %s error during %s channel setup state=%s\n",
                CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event],
-               (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+               (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX",
                fsm_getstate_str(fi));
 
-       if (CHANNEL_DIRECTION(ch->flags) == READ) {
+       if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {
                fsm_newstate(fi, CTC_STATE_RXERR);
                fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
        } else {
@@ -945,7 +947,7 @@ static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
        fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
 
        fsm_newstate(fi, CTC_STATE_DTERM);
-       ch2 = priv->channel[WRITE];
+       ch2 = priv->channel[CTCM_WRITE];
        fsm_newstate(ch2->fsm, CTC_STATE_DTERM);
 
        ccw_device_halt(ch->cdev, (unsigned long)ch);
@@ -1074,13 +1076,13 @@ static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
        fsm_deltimer(&ch->timer);
        CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
                "%s: %s: %s unrecoverable channel error",
-                       CTCM_FUNTAIL, ch->id, rd == READ ? "RX" : "TX");
+                       CTCM_FUNTAIL, ch->id, rd == CTCM_READ ? "RX" : "TX");
 
        if (IS_MPC(ch)) {
                priv->stats.tx_dropped++;
                priv->stats.tx_errors++;
        }
-       if (rd == READ) {
+       if (rd == CTCM_READ) {
                fsm_newstate(fi, CTC_STATE_RXERR);
                fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
        } else {
@@ -1503,7 +1505,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
        switch (fsm_getstate(fi)) {
        case CTC_STATE_STARTRETRY:
        case CTC_STATE_SETUPWAIT:
-               if (CHANNEL_DIRECTION(ch->flags) == READ) {
+               if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {
                        ctcmpc_chx_rxidle(fi, event, arg);
                } else {
                        fsm_newstate(fi, CTC_STATE_TXIDLE);
@@ -1514,7 +1516,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
                break;
        };
 
-       fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+       fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)
                     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
 
 done:
@@ -1753,8 +1755,8 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
        struct net_device *dev = ach->netdev;
        struct ctcm_priv *priv = dev->ml_priv;
        struct mpc_group *grp = priv->mpcg;
-       struct channel *wch = priv->channel[WRITE];
-       struct channel *rch = priv->channel[READ];
+       struct channel *wch = priv->channel[CTCM_WRITE];
+       struct channel *rch = priv->channel[CTCM_READ];
        struct sk_buff *skb;
        struct th_sweep *header;
        int rc = 0;
@@ -2070,7 +2072,7 @@ static void dev_action_start(fsm_instance *fi, int event, void *arg)
        fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
        if (IS_MPC(priv))
                priv->mpcg->channels_terminating = 0;
-       for (direction = READ; direction <= WRITE; direction++) {
+       for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
                struct channel *ch = priv->channel[direction];
                fsm_event(ch->fsm, CTC_EVENT_START, ch);
        }
@@ -2092,7 +2094,7 @@ static void dev_action_stop(fsm_instance *fi, int event, void *arg)
        CTCMY_DBF_DEV_NAME(SETUP, dev, "");
 
        fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-       for (direction = READ; direction <= WRITE; direction++) {
+       for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
                struct channel *ch = priv->channel[direction];
                fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
                ch->th_seq_num = 0x00;
@@ -2183,11 +2185,11 @@ static void dev_action_chup(fsm_instance *fi, int event, void *arg)
 
        if (IS_MPC(priv)) {
                if (event == DEV_EVENT_RXUP)
-                       mpc_channel_action(priv->channel[READ],
-                               READ, MPC_CHANNEL_ADD);
+                       mpc_channel_action(priv->channel[CTCM_READ],
+                               CTCM_READ, MPC_CHANNEL_ADD);
                else
-                       mpc_channel_action(priv->channel[WRITE],
-                               WRITE, MPC_CHANNEL_ADD);
+                       mpc_channel_action(priv->channel[CTCM_WRITE],
+                               CTCM_WRITE, MPC_CHANNEL_ADD);
        }
 }
 
@@ -2239,11 +2241,11 @@ static void dev_action_chdown(fsm_instance *fi, int event, void *arg)
        }
        if (IS_MPC(priv)) {
                if (event == DEV_EVENT_RXDOWN)
-                       mpc_channel_action(priv->channel[READ],
-                               READ, MPC_CHANNEL_REMOVE);
+                       mpc_channel_action(priv->channel[CTCM_READ],
+                               CTCM_READ, MPC_CHANNEL_REMOVE);
                else
-                       mpc_channel_action(priv->channel[WRITE],
-                               WRITE, MPC_CHANNEL_REMOVE);
+                       mpc_channel_action(priv->channel[CTCM_WRITE],
+                               CTCM_WRITE, MPC_CHANNEL_REMOVE);
        }
 }
 
index 4ecafbf91211b72775315a95e20a322e0e11e834..6edf20b62de5bae28214275931f0db9fd1fcd1f2 100644 (file)
@@ -267,7 +267,7 @@ static struct channel *channel_get(enum ctcm_channel_types type,
                else {
                        ch->flags |= CHANNEL_FLAGS_INUSE;
                        ch->flags &= ~CHANNEL_FLAGS_RWMASK;
-                       ch->flags |= (direction == WRITE)
+                       ch->flags |= (direction == CTCM_WRITE)
                            ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
                        fsm_newstate(ch->fsm, CTC_STATE_STOPPED);
                }
@@ -388,7 +388,8 @@ int ctcm_ch_alloc_buffer(struct channel *ch)
                CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
                        "%s(%s): %s trans_skb allocation error",
                        CTCM_FUNTAIL, ch->id,
-                       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+                       (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?
+                               "RX" : "TX");
                return -ENOMEM;
        }
 
@@ -399,7 +400,8 @@ int ctcm_ch_alloc_buffer(struct channel *ch)
                CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
                        "%s(%s): %s set norm_cda failed",
                        CTCM_FUNTAIL, ch->id,
-                       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+                       (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?
+                               "RX" : "TX");
                return -ENOMEM;
        }
 
@@ -603,14 +605,14 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
 
        priv = dev->ml_priv;
        grp = priv->mpcg;
-       ch = priv->channel[WRITE];
+       ch = priv->channel[CTCM_WRITE];
 
        /* sweep processing is not complete until response and request */
        /* has completed for all read channels in group                */
        if (grp->in_sweep == 0) {
                grp->in_sweep = 1;
-               grp->sweep_rsp_pend_num = grp->active_channels[READ];
-               grp->sweep_req_pend_num = grp->active_channels[READ];
+               grp->sweep_rsp_pend_num = grp->active_channels[CTCM_READ];
+               grp->sweep_req_pend_num = grp->active_channels[CTCM_READ];
        }
 
        sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
@@ -911,7 +913,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
 
        dev->trans_start = jiffies;
-       if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
+       if (ctcm_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0)
                return NETDEV_TX_BUSY;
        return NETDEV_TX_OK;
 }
@@ -994,7 +996,7 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
        }
 
        dev->trans_start = jiffies;
-       if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
+       if (ctcmpc_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0) {
                CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
                        "%s(%s): device error - dropped",
                                        CTCM_FUNTAIL, dev->name);
@@ -1035,7 +1037,7 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
                return -EINVAL;
 
        priv = dev->ml_priv;
-       max_bufsize = priv->channel[READ]->max_bufsize;
+       max_bufsize = priv->channel[CTCM_READ]->max_bufsize;
 
        if (IS_MPC(priv)) {
                if (new_mtu > max_bufsize - TH_HEADER_LENGTH)
@@ -1226,10 +1228,10 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
        priv = dev_get_drvdata(&cgdev->dev);
 
        /* Try to extract channel from driver data. */
-       if (priv->channel[READ]->cdev == cdev)
-               ch = priv->channel[READ];
-       else if (priv->channel[WRITE]->cdev == cdev)
-               ch = priv->channel[WRITE];
+       if (priv->channel[CTCM_READ]->cdev == cdev)
+               ch = priv->channel[CTCM_READ];
+       else if (priv->channel[CTCM_WRITE]->cdev == cdev)
+               ch = priv->channel[CTCM_WRITE];
        else {
                dev_err(&cdev->dev,
                        "%s: Internal error: Can't determine channel for "
@@ -1587,13 +1589,13 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
                goto out_ccw2;
        }
 
-       for (direction = READ; direction <= WRITE; direction++) {
+       for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
                priv->channel[direction] =
-                   channel_get(type, direction == READ ? read_id : write_id,
-                               direction);
+                       channel_get(type, direction == CTCM_READ ?
+                               read_id : write_id, direction);
                if (priv->channel[direction] == NULL) {
-                       if (direction == WRITE)
-                               channel_free(priv->channel[READ]);
+                       if (direction == CTCM_WRITE)
+                               channel_free(priv->channel[CTCM_READ]);
                        goto out_dev;
                }
                priv->channel[direction]->netdev = dev;
@@ -1617,13 +1619,13 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
 
        dev_info(&dev->dev,
                "setup OK : r/w = %s/%s, protocol : %d\n",
-                       priv->channel[READ]->id,
-                       priv->channel[WRITE]->id, priv->protocol);
+                       priv->channel[CTCM_READ]->id,
+                       priv->channel[CTCM_WRITE]->id, priv->protocol);
 
        CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
                "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
-                       priv->channel[READ]->id,
-                       priv->channel[WRITE]->id, priv->protocol);
+                       priv->channel[CTCM_READ]->id,
+                       priv->channel[CTCM_WRITE]->id, priv->protocol);
 
        return 0;
 out_unregister:
@@ -1635,10 +1637,10 @@ out_ccw2:
 out_ccw1:
        ccw_device_set_offline(cgdev->cdev[0]);
 out_remove_channel2:
-       readc = channel_get(type, read_id, READ);
+       readc = channel_get(type, read_id, CTCM_READ);
        channel_remove(readc);
 out_remove_channel1:
-       writec = channel_get(type, write_id, WRITE);
+       writec = channel_get(type, write_id, CTCM_WRITE);
        channel_remove(writec);
 out_err_result:
        return result;
@@ -1660,19 +1662,19 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
        if (!priv)
                return -ENODEV;
 
-       if (priv->channel[READ]) {
-               dev = priv->channel[READ]->netdev;
+       if (priv->channel[CTCM_READ]) {
+               dev = priv->channel[CTCM_READ]->netdev;
                CTCM_DBF_DEV(SETUP, dev, "");
                /* Close the device */
                ctcm_close(dev);
                dev->flags &= ~IFF_RUNNING;
                ctcm_remove_attributes(&cgdev->dev);
-               channel_free(priv->channel[READ]);
+               channel_free(priv->channel[CTCM_READ]);
        } else
                dev = NULL;
 
-       if (priv->channel[WRITE])
-               channel_free(priv->channel[WRITE]);
+       if (priv->channel[CTCM_WRITE])
+               channel_free(priv->channel[CTCM_WRITE]);
 
        if (dev) {
                unregister_netdev(dev);
@@ -1685,11 +1687,11 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
        ccw_device_set_offline(cgdev->cdev[1]);
        ccw_device_set_offline(cgdev->cdev[0]);
 
-       if (priv->channel[READ])
-               channel_remove(priv->channel[READ]);
-       if (priv->channel[WRITE])
-               channel_remove(priv->channel[WRITE]);
-       priv->channel[READ] = priv->channel[WRITE] = NULL;
+       if (priv->channel[CTCM_READ])
+               channel_remove(priv->channel[CTCM_READ]);
+       if (priv->channel[CTCM_WRITE])
+               channel_remove(priv->channel[CTCM_WRITE]);
+       priv->channel[CTCM_READ] = priv->channel[CTCM_WRITE] = NULL;
 
        return 0;
 
@@ -1720,11 +1722,11 @@ static int ctcm_pm_suspend(struct ccwgroup_device *gdev)
 
        if (gdev->state == CCWGROUP_OFFLINE)
                return 0;
-       netif_device_detach(priv->channel[READ]->netdev);
-       ctcm_close(priv->channel[READ]->netdev);
+       netif_device_detach(priv->channel[CTCM_READ]->netdev);
+       ctcm_close(priv->channel[CTCM_READ]->netdev);
        if (!wait_event_timeout(priv->fsm->wait_q,
            fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) {
-               netif_device_attach(priv->channel[READ]->netdev);
+               netif_device_attach(priv->channel[CTCM_READ]->netdev);
                return -EBUSY;
        }
        ccw_device_set_offline(gdev->cdev[1]);
@@ -1745,9 +1747,9 @@ static int ctcm_pm_resume(struct ccwgroup_device *gdev)
        rc = ccw_device_set_online(gdev->cdev[0]);
        if (rc)
                goto err_out;
-       ctcm_open(priv->channel[READ]->netdev);
+       ctcm_open(priv->channel[CTCM_READ]->netdev);
 err_out:
-       netif_device_attach(priv->channel[READ]->netdev);
+       netif_device_attach(priv->channel[CTCM_READ]->netdev);
        return rc;
 }
 
index d34fa14f44e767c7ddf866b2d325406c48607ce2..24d5215eb0c40af4816115579bde366149eb159f 100644 (file)
@@ -111,8 +111,8 @@ enum ctcm_channel_types {
 
 #define CTCM_INITIAL_BLOCKLEN  2
 
-#define READ                   0
-#define WRITE                  1
+#define CTCM_READ              0
+#define CTCM_WRITE             1
 
 #define CTCM_ID_SIZE           20+3
 
index 87c24d2936d6e34d1de09da7ebe27aff148d8f61..2861e78773cb5f0e4ee319e4cc0928a00953c717 100644 (file)
@@ -419,8 +419,8 @@ void ctc_mpc_establish_connectivity(int port_num,
                return;
        priv = dev->ml_priv;
        grp = priv->mpcg;
-       rch = priv->channel[READ];
-       wch = priv->channel[WRITE];
+       rch = priv->channel[CTCM_READ];
+       wch = priv->channel[CTCM_WRITE];
 
        CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
                        "%s(%s): state=%s",
@@ -578,7 +578,7 @@ void ctc_mpc_flow_control(int port_num, int flowc)
                        "%s: %s: flowc = %d",
                                CTCM_FUNTAIL, dev->name, flowc);
 
-       rch = priv->channel[READ];
+       rch = priv->channel[CTCM_READ];
 
        mpcg_state = fsm_getstate(grp->fsm);
        switch (flowc) {
@@ -622,7 +622,7 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
        struct net_device *dev = rch->netdev;
        struct ctcm_priv   *priv = dev->ml_priv;
        struct mpc_group  *grp = priv->mpcg;
-       struct channel    *ch = priv->channel[WRITE];
+       struct channel    *ch = priv->channel[CTCM_WRITE];
 
        CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id);
        CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
@@ -656,7 +656,7 @@ static void ctcmpc_send_sweep_resp(struct channel *rch)
        int rc = 0;
        struct th_sweep *header;
        struct sk_buff *sweep_skb;
-       struct channel *ch  = priv->channel[WRITE];
+       struct channel *ch  = priv->channel[CTCM_WRITE];
 
        CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id);
 
@@ -712,7 +712,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
        struct net_device *dev     = rch->netdev;
        struct ctcm_priv  *priv = dev->ml_priv;
        struct mpc_group  *grp  = priv->mpcg;
-       struct channel    *ch      = priv->channel[WRITE];
+       struct channel    *ch      = priv->channel[CTCM_WRITE];
 
        if (do_debug)
                CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
@@ -721,8 +721,8 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
        if (grp->in_sweep == 0) {
                grp->in_sweep = 1;
                ctcm_test_and_set_busy(dev);
-               grp->sweep_req_pend_num = grp->active_channels[READ];
-               grp->sweep_rsp_pend_num = grp->active_channels[READ];
+               grp->sweep_req_pend_num = grp->active_channels[CTCM_READ];
+               grp->sweep_rsp_pend_num = grp->active_channels[CTCM_READ];
        }
 
        CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
@@ -906,14 +906,14 @@ void mpc_group_ready(unsigned long adev)
        fsm_newstate(grp->fsm, MPCG_STATE_READY);
 
        /* Put up a read on the channel */
-       ch = priv->channel[READ];
+       ch = priv->channel[CTCM_READ];
        ch->pdu_seq = 0;
        CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
                        __func__, ch->pdu_seq);
 
        ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
        /* Put the write channel in idle state */
-       ch = priv->channel[WRITE];
+       ch = priv->channel[CTCM_WRITE];
        if (ch->collect_len > 0) {
                spin_lock(&ch->collect_lock);
                ctcm_purge_skb_queue(&ch->collect_queue);
@@ -960,7 +960,8 @@ void mpc_channel_action(struct channel *ch, int direction, int action)
                "%s: %i / Grp:%s total_channels=%i, active_channels: "
                "read=%i, write=%i\n", __func__, action,
                fsm_getstate_str(grp->fsm), grp->num_channel_paths,
-               grp->active_channels[READ], grp->active_channels[WRITE]);
+               grp->active_channels[CTCM_READ],
+               grp->active_channels[CTCM_WRITE]);
 
        if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
                grp->num_channel_paths++;
@@ -994,10 +995,11 @@ void mpc_channel_action(struct channel *ch, int direction, int action)
                                grp->xid_skb->data,
                                grp->xid_skb->len);
 
-               ch->xid->xid2_dlc_type = ((CHANNEL_DIRECTION(ch->flags) == READ)
+               ch->xid->xid2_dlc_type =
+                       ((CHANNEL_DIRECTION(ch->flags) == CTCM_READ)
                                ? XID2_READ_SIDE : XID2_WRITE_SIDE);
 
-               if (CHANNEL_DIRECTION(ch->flags) == WRITE)
+               if (CHANNEL_DIRECTION(ch->flags) == CTCM_WRITE)
                        ch->xid->xid2_buf_len = 0x00;
 
                ch->xid_skb->data = ch->xid_skb_data;
@@ -1006,8 +1008,8 @@ void mpc_channel_action(struct channel *ch, int direction, int action)
 
                fsm_newstate(ch->fsm, CH_XID0_PENDING);
 
-               if ((grp->active_channels[READ]  > 0) &&
-                   (grp->active_channels[WRITE] > 0) &&
+               if ((grp->active_channels[CTCM_READ] > 0) &&
+                   (grp->active_channels[CTCM_WRITE] > 0) &&
                        (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
                        fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
                        CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
@@ -1027,10 +1029,10 @@ void mpc_channel_action(struct channel *ch, int direction, int action)
                if (grp->channels_terminating)
                                        goto done;
 
-               if (((grp->active_channels[READ] == 0) &&
-                                       (grp->active_channels[WRITE] > 0))
-                       || ((grp->active_channels[WRITE] == 0) &&
-                                       (grp->active_channels[READ] > 0)))
+               if (((grp->active_channels[CTCM_READ] == 0) &&
+                                       (grp->active_channels[CTCM_WRITE] > 0))
+                       || ((grp->active_channels[CTCM_WRITE] == 0) &&
+                                       (grp->active_channels[CTCM_READ] > 0)))
                        fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
        }
 done:
@@ -1038,7 +1040,8 @@ done:
                "exit %s: %i / Grp:%s total_channels=%i, active_channels: "
                "read=%i, write=%i\n", __func__, action,
                fsm_getstate_str(grp->fsm), grp->num_channel_paths,
-               grp->active_channels[READ], grp->active_channels[WRITE]);
+               grp->active_channels[CTCM_READ],
+               grp->active_channels[CTCM_WRITE]);
 
        CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
 }
@@ -1392,8 +1395,8 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
                (grp->port_persist == 0))
                fsm_deltimer(&priv->restart_timer);
 
-       wch = priv->channel[WRITE];
-       rch = priv->channel[READ];
+       wch = priv->channel[CTCM_WRITE];
+       rch = priv->channel[CTCM_READ];
 
        switch (grp->saved_state) {
        case MPCG_STATE_RESET:
@@ -1480,8 +1483,8 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
 
        priv = dev->ml_priv;
        grp = priv->mpcg;
-       wch = priv->channel[WRITE];
-       rch = priv->channel[READ];
+       wch = priv->channel[CTCM_WRITE];
+       rch = priv->channel[CTCM_READ];
 
        switch (fsm_getstate(grp->fsm)) {
        case MPCG_STATE_XID2INITW:
@@ -1586,7 +1589,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
        CTCM_D3_DUMP((char *)xid, XID2_LENGTH);
 
        /*the received direction should be the opposite of ours  */
-       if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
+       if (((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? XID2_WRITE_SIDE :
                                XID2_READ_SIDE) != xid->xid2_dlc_type) {
                rc = 2;
                /* XID REJECTED: r/w channel pairing mismatch */
@@ -1912,7 +1915,7 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
        if (grp == NULL)
                return;
 
-       for (direction = READ; direction <= WRITE; direction++) {
+       for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
                struct channel *ch = priv->channel[direction];
                struct xid2 *thisxid = ch->xid;
                ch->xid_skb->data = ch->xid_skb_data;
@@ -2152,14 +2155,15 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
                        return -ENOMEM;
                }
 
-               *((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
-               priv->channel[READ]->pdu_seq++;
+               *((__u32 *)skb_push(skb, 4)) =
+                       priv->channel[CTCM_READ]->pdu_seq;
+               priv->channel[CTCM_READ]->pdu_seq++;
                CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
-                               __func__, priv->channel[READ]->pdu_seq);
+                               __func__, priv->channel[CTCM_READ]->pdu_seq);
 
                /* receipt of CC03 resets anticipated sequence number on
                      receiving side */
-               priv->channel[READ]->pdu_seq = 0x00;
+               priv->channel[CTCM_READ]->pdu_seq = 0x00;
                skb_reset_mac_header(skb);
                skb->dev = dev;
                skb->protocol = htons(ETH_P_SNAP);
index 2b24550e865e672e9ef6761b667beba2231b235e..8305319b2a846c31328f5b773e8e0177cf6d41d0 100644 (file)
@@ -38,8 +38,8 @@ static ssize_t ctcm_buffer_write(struct device *dev,
        int bs1;
        struct ctcm_priv *priv = dev_get_drvdata(dev);
 
-       if (!(priv && priv->channel[READ] &&
-                       (ndev = priv->channel[READ]->netdev))) {
+       ndev = priv->channel[CTCM_READ]->netdev;
+       if (!(priv && priv->channel[CTCM_READ] && ndev)) {
                CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
                return -ENODEV;
        }
@@ -55,12 +55,12 @@ static ssize_t ctcm_buffer_write(struct device *dev,
            (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
                                        goto einval;
 
-       priv->channel[READ]->max_bufsize = bs1;
-       priv->channel[WRITE]->max_bufsize = bs1;
+       priv->channel[CTCM_READ]->max_bufsize = bs1;
+       priv->channel[CTCM_WRITE]->max_bufsize = bs1;
        if (!(ndev->flags & IFF_RUNNING))
                ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
-       priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
-       priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+       priv->channel[CTCM_READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+       priv->channel[CTCM_WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
 
        CTCM_DBF_DEV(SETUP, ndev, buf);
        return count;
@@ -85,9 +85,9 @@ static void ctcm_print_statistics(struct ctcm_priv *priv)
        p += sprintf(p, "  Device FSM state: %s\n",
                     fsm_getstate_str(priv->fsm));
        p += sprintf(p, "  RX channel FSM state: %s\n",
-                    fsm_getstate_str(priv->channel[READ]->fsm));
+                    fsm_getstate_str(priv->channel[CTCM_READ]->fsm));
        p += sprintf(p, "  TX channel FSM state: %s\n",
-                    fsm_getstate_str(priv->channel[WRITE]->fsm));
+                    fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm));
        p += sprintf(p, "  Max. TX buffer used: %ld\n",
                     priv->channel[WRITE]->prof.maxmulti);
        p += sprintf(p, "  Max. chained SKBs: %ld\n",
@@ -102,7 +102,7 @@ static void ctcm_print_statistics(struct ctcm_priv *priv)
                     priv->channel[WRITE]->prof.tx_time);
 
        printk(KERN_INFO "Statistics for %s:\n%s",
-                               priv->channel[WRITE]->netdev->name, sbuf);
+                               priv->channel[CTCM_WRITE]->netdev->name, sbuf);
        kfree(sbuf);
        return;
 }
@@ -125,7 +125,7 @@ static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
                return -ENODEV;
        /* Reset statistics */
        memset(&priv->channel[WRITE]->prof, 0,
-                               sizeof(priv->channel[WRITE]->prof));
+                               sizeof(priv->channel[CTCM_WRITE]->prof));
        return count;
 }
 
index 4d2992aadfb736a36bf0570f048b34a4704ae5fb..b036677df8c445420906c722d00611dedcaf8b0a 100644 (file)
@@ -574,16 +574,21 @@ config IT87_WDT
          be called it87_wdt.
 
 config HP_WATCHDOG
-       tristate "HP Proliant iLO 2 Hardware Watchdog Timer"
+       tristate "HP Proliant iLO2+ Hardware Watchdog Timer"
        depends on X86
        help
          A software monitoring watchdog and NMI sourcing driver. This driver
-         will detect lockups and provide stack trace. Also, when an NMI
-         occurs this driver will make the necessary BIOS calls to log
-         the cause of the NMI. This is a driver that will only load on a
-         HP ProLiant system with a minimum of iLO2 support.
-         To compile this driver as a module, choose M here: the
-         module will be called hpwdt.
+         will detect lockups and provide a stack trace. This is a driver that
+         will only load on a HP ProLiant system with a minimum of iLO2 support.
+         To compile this driver as a module, choose M here: the module will be
+         called hpwdt.
+
+config HPWDT_NMI_DECODING
+       bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
+       depends on HP_WATCHDOG
+       help
+         When an NMI occurs this feature will make the necessary BIOS calls to
+         log the cause of the NMI.
 
 config SC1200_WDT
        tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
index fd312fc8940e12f96246427a7ce3b855edcca7cf..3d77116e463410dac81b6c530c74d5a55f9c7afc 100644 (file)
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/nmi.h>
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/kdebug.h>
 #include <linux/moduleparam.h>
-#include <linux/notifier.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
+#ifdef CONFIG_HPWDT_NMI_DECODING
 #include <linux/dmi.h>
-#include <linux/efi.h>
-#include <linux/string.h>
-#include <linux/bootmem.h>
-#include <asm/desc.h>
+#include <linux/spinlock.h>
+#include <linux/nmi.h>
+#include <linux/kdebug.h>
+#include <linux/notifier.h>
 #include <asm/cacheflush.h>
+#endif /* CONFIG_HPWDT_NMI_DECODING */
+
+#define HPWDT_VERSION                  "1.2.0"
+#define SECS_TO_TICKS(secs)            ((secs) * 1000 / 128)
+#define TICKS_TO_SECS(ticks)           ((ticks) * 128 / 1000)
+#define HPWDT_MAX_TIMER                        TICKS_TO_SECS(65535)
+#define DEFAULT_MARGIN                 30
+
+static unsigned int soft_margin = DEFAULT_MARGIN;      /* in seconds */
+static unsigned int reload;                    /* the computed soft_margin */
+static int nowayout = WATCHDOG_NOWAYOUT;
+static char expect_release;
+static unsigned long hpwdt_is_open;
+
+static void __iomem *pci_mem_addr;             /* the PCI-memory address */
+static unsigned long __iomem *hpwdt_timer_reg;
+static unsigned long __iomem *hpwdt_timer_con;
 
+static struct pci_device_id hpwdt_devices[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },   /* iLO2 */
+       { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },       /* iLO3 */
+       {0},                    /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, hpwdt_devices);
+
+#ifdef CONFIG_HPWDT_NMI_DECODING
 #define PCI_BIOS32_SD_VALUE            0x5F32335F      /* "_32_" */
 #define CRU_BIOS_SIGNATURE_VALUE       0x55524324
 #define PCI_BIOS32_PARAGRAPH_LEN       16
 #define PCI_ROM_BASE1                  0x000F0000
 #define ROM_SIZE                       0x10000
-#define HPWDT_VERSION                  "1.1.1"
 
 struct bios32_service_dir {
        u32 signature;
@@ -112,37 +129,17 @@ struct cmn_registers {
        u32 reflags;
 }  __attribute__((packed));
 
-#define DEFAULT_MARGIN 30
-static unsigned int soft_margin = DEFAULT_MARGIN;      /* in seconds */
-static unsigned int reload;                    /* the computed soft_margin */
-static int nowayout = WATCHDOG_NOWAYOUT;
-static char expect_release;
-static unsigned long hpwdt_is_open;
+static unsigned int hpwdt_nmi_decoding;
 static unsigned int allow_kdump;
-static unsigned int hpwdt_nmi_sourcing;
 static unsigned int priority;          /* hpwdt at end of die_notify list */
-
-static void __iomem *pci_mem_addr;             /* the PCI-memory address */
-static unsigned long __iomem *hpwdt_timer_reg;
-static unsigned long __iomem *hpwdt_timer_con;
-
 static DEFINE_SPINLOCK(rom_lock);
-
 static void *cru_rom_addr;
-
 static struct cmn_registers cmn_regs;
 
-static struct pci_device_id hpwdt_devices[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },
-       { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },
-       {0},                    /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, hpwdt_devices);
-
 extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
                                                unsigned long *pRomEntry);
 
-#ifndef CONFIG_X86_64
+#ifdef CONFIG_X86_32
 /* --32 Bit Bios------------------------------------------------------------ */
 
 #define HPWDT_ARCH     32
@@ -331,8 +328,9 @@ static int __devinit detect_cru_service(void)
        iounmap(p);
        return rc;
 }
-
-#else
+/* ------------------------------------------------------------------------- */
+#endif /* CONFIG_X86_32 */
+#ifdef CONFIG_X86_64
 /* --64 Bit Bios------------------------------------------------------------ */
 
 #define HPWDT_ARCH     64
@@ -410,17 +408,16 @@ static int __devinit detect_cru_service(void)
        /* if cru_rom_addr has been set then we found a CRU service */
        return ((cru_rom_addr != NULL) ? 0 : -ENODEV);
 }
-
 /* ------------------------------------------------------------------------- */
-
-#endif
+#endif /* CONFIG_X86_64 */
+#endif /* CONFIG_HPWDT_NMI_DECODING */
 
 /*
  *     Watchdog operations
  */
 static void hpwdt_start(void)
 {
-       reload = (soft_margin * 1000) / 128;
+       reload = SECS_TO_TICKS(soft_margin);
        iowrite16(reload, hpwdt_timer_reg);
        iowrite16(0x85, hpwdt_timer_con);
 }
@@ -441,8 +438,7 @@ static void hpwdt_ping(void)
 
 static int hpwdt_change_timer(int new_margin)
 {
-       /* Arbitrary, can't find the card's limits */
-       if (new_margin < 5 || new_margin > 600) {
+       if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) {
                printk(KERN_WARNING
                        "hpwdt: New value passed in is invalid: %d seconds.\n",
                        new_margin);
@@ -453,11 +449,17 @@ static int hpwdt_change_timer(int new_margin)
        printk(KERN_DEBUG
                "hpwdt: New timer passed in is %d seconds.\n",
                new_margin);
-       reload = (soft_margin * 1000) / 128;
+       reload = SECS_TO_TICKS(soft_margin);
 
        return 0;
 }
 
+static int hpwdt_time_left(void)
+{
+       return TICKS_TO_SECS(ioread16(hpwdt_timer_reg));
+}
+
+#ifdef CONFIG_HPWDT_NMI_DECODING
 /*
  *     NMI Handler
  */
@@ -468,26 +470,29 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
        static int die_nmi_called;
 
        if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI)
-               return NOTIFY_OK;
-
-       if (hpwdt_nmi_sourcing) {
-               spin_lock_irqsave(&rom_lock, rom_pl);
-               if (!die_nmi_called)
-                       asminline_call(&cmn_regs, cru_rom_addr);
-               die_nmi_called = 1;
-               spin_unlock_irqrestore(&rom_lock, rom_pl);
-               if (cmn_regs.u1.ral == 0) {
-                       printk(KERN_WARNING "hpwdt: An NMI occurred, "
-                               "but unable to determine source.\n");
-               } else {
-                       if (allow_kdump)
-                               hpwdt_stop();
-                       panic("An NMI occurred, please see the Integrated "
-                               "Management Log for details.\n");
-               }
+               goto out;
+
+       if (!hpwdt_nmi_decoding)
+               goto out;
+
+       spin_lock_irqsave(&rom_lock, rom_pl);
+       if (!die_nmi_called)
+               asminline_call(&cmn_regs, cru_rom_addr);
+       die_nmi_called = 1;
+       spin_unlock_irqrestore(&rom_lock, rom_pl);
+       if (cmn_regs.u1.ral == 0) {
+               printk(KERN_WARNING "hpwdt: An NMI occurred, "
+                       "but unable to determine source.\n");
+       } else {
+               if (allow_kdump)
+                       hpwdt_stop();
+               panic("An NMI occurred, please see the Integrated "
+                       "Management Log for details.\n");
        }
+out:
        return NOTIFY_OK;
 }
+#endif /* CONFIG_HPWDT_NMI_DECODING */
 
 /*
  *     /dev/watchdog handling
@@ -557,7 +562,7 @@ static const struct watchdog_info ident = {
        .options = WDIOF_SETTIMEOUT |
                   WDIOF_KEEPALIVEPING |
                   WDIOF_MAGICCLOSE,
-       .identity = "HP iLO2 HW Watchdog Timer",
+       .identity = "HP iLO2+ HW Watchdog Timer",
 };
 
 static long hpwdt_ioctl(struct file *file, unsigned int cmd,
@@ -599,6 +604,10 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd,
        case WDIOC_GETTIMEOUT:
                ret = put_user(soft_margin, p);
                break;
+
+       case WDIOC_GETTIMELEFT:
+               ret = put_user(hpwdt_time_left(), p);
+               break;
        }
        return ret;
 }
@@ -621,79 +630,44 @@ static struct miscdevice hpwdt_miscdev = {
        .fops = &hpwdt_fops,
 };
 
+#ifdef CONFIG_HPWDT_NMI_DECODING
 static struct notifier_block die_notifier = {
        .notifier_call = hpwdt_pretimeout,
        .priority = 0,
 };
+#endif /* CONFIG_HPWDT_NMI_DECODING */
 
 /*
  *     Init & Exit
  */
 
+#ifdef CONFIG_HPWDT_NMI_DECODING
 #ifdef ARCH_HAS_NMI_WATCHDOG
-static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
+static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
        /*
         * If nmi_watchdog is turned off then we can turn on
-        * our nmi sourcing capability.
+        * our nmi decoding capability.
         */
        if (!nmi_watchdog_active())
-               hpwdt_nmi_sourcing = 1;
+               hpwdt_nmi_decoding = 1;
        else
-               dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this "
+               dev_warn(&dev->dev, "NMI decoding is disabled. To enable this "
                        "functionality you must reboot with nmi_watchdog=0 "
                        "and load the hpwdt driver with priority=1.\n");
 }
 #else
-static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev)
+static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
-       dev_warn(&dev->dev, "NMI sourcing is disabled. "
+       dev_warn(&dev->dev, "NMI decoding is disabled. "
                "Your kernel does not support a NMI Watchdog.\n");
 }
-#endif
+#endif /* ARCH_HAS_NMI_WATCHDOG */
 
-static int __devinit hpwdt_init_one(struct pci_dev *dev,
-                                       const struct pci_device_id *ent)
+static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
 {
        int retval;
 
-       /*
-        * Check if we can do NMI sourcing or not
-        */
-       hpwdt_check_nmi_sourcing(dev);
-
-       /*
-        * First let's find out if we are on an iLO2 server. We will
-        * not run on a legacy ASM box.
-        * So we only support the G5 ProLiant servers and higher.
-        */
-       if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
-               dev_warn(&dev->dev,
-                       "This server does not have an iLO2 ASIC.\n");
-               return -ENODEV;
-       }
-
-       if (pci_enable_device(dev)) {
-               dev_warn(&dev->dev,
-                       "Not possible to enable PCI Device: 0x%x:0x%x.\n",
-                       ent->vendor, ent->device);
-               return -ENODEV;
-       }
-
-       pci_mem_addr = pci_iomap(dev, 1, 0x80);
-       if (!pci_mem_addr) {
-               dev_warn(&dev->dev,
-                       "Unable to detect the iLO2 server memory.\n");
-               retval = -ENOMEM;
-               goto error_pci_iomap;
-       }
-       hpwdt_timer_reg = pci_mem_addr + 0x70;
-       hpwdt_timer_con = pci_mem_addr + 0x72;
-
-       /* Make sure that we have a valid soft_margin */
-       if (hpwdt_change_timer(soft_margin))
-               hpwdt_change_timer(DEFAULT_MARGIN);
-
        /*
         * We need to map the ROM to get the CRU service.
         * For 32 bit Operating Systems we need to go through the 32 Bit
@@ -705,7 +679,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
                dev_warn(&dev->dev,
                        "Unable to detect the %d Bit CRU Service.\n",
                        HPWDT_ARCH);
-               goto error_get_cru;
+               return retval;
        }
 
        /*
@@ -728,9 +702,87 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
                dev_warn(&dev->dev,
                        "Unable to register a die notifier (err=%d).\n",
                        retval);
-               goto error_die_notifier;
+               if (cru_rom_addr)
+                       iounmap(cru_rom_addr);
        }
 
+       dev_info(&dev->dev,
+                       "HP Watchdog Timer Driver: NMI decoding initialized"
+                       ", allow kernel dump: %s (default = 0/OFF)"
+                       ", priority: %s (default = 0/LAST).\n",
+                       (allow_kdump == 0) ? "OFF" : "ON",
+                       (priority == 0) ? "LAST" : "FIRST");
+       return 0;
+}
+
+static void __devexit hpwdt_exit_nmi_decoding(void)
+{
+       unregister_die_notifier(&die_notifier);
+       if (cru_rom_addr)
+               iounmap(cru_rom_addr);
+}
+#else /* !CONFIG_HPWDT_NMI_DECODING */
+static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+{
+}
+
+static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
+{
+       return 0;
+}
+
+static void __devexit hpwdt_exit_nmi_decoding(void)
+{
+}
+#endif /* CONFIG_HPWDT_NMI_DECODING */
+
+static int __devinit hpwdt_init_one(struct pci_dev *dev,
+                                       const struct pci_device_id *ent)
+{
+       int retval;
+
+       /*
+        * Check if we can do NMI decoding or not
+        */
+       hpwdt_check_nmi_decoding(dev);
+
+       /*
+        * First let's find out if we are on an iLO2+ server. We will
+        * not run on a legacy ASM box.
+        * So we only support the G5 ProLiant servers and higher.
+        */
+       if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
+               dev_warn(&dev->dev,
+                       "This server does not have an iLO2+ ASIC.\n");
+               return -ENODEV;
+       }
+
+       if (pci_enable_device(dev)) {
+               dev_warn(&dev->dev,
+                       "Not possible to enable PCI Device: 0x%x:0x%x.\n",
+                       ent->vendor, ent->device);
+               return -ENODEV;
+       }
+
+       pci_mem_addr = pci_iomap(dev, 1, 0x80);
+       if (!pci_mem_addr) {
+               dev_warn(&dev->dev,
+                       "Unable to detect the iLO2+ server memory.\n");
+               retval = -ENOMEM;
+               goto error_pci_iomap;
+       }
+       hpwdt_timer_reg = pci_mem_addr + 0x70;
+       hpwdt_timer_con = pci_mem_addr + 0x72;
+
+       /* Make sure that we have a valid soft_margin */
+       if (hpwdt_change_timer(soft_margin))
+               hpwdt_change_timer(DEFAULT_MARGIN);
+
+       /* Initialize NMI Decoding functionality */
+       retval = hpwdt_init_nmi_decoding(dev);
+       if (retval != 0)
+               goto error_init_nmi_decoding;
+
        retval = misc_register(&hpwdt_miscdev);
        if (retval < 0) {
                dev_warn(&dev->dev,
@@ -739,23 +791,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
                goto error_misc_register;
        }
 
-       printk(KERN_INFO
-               "hp Watchdog Timer Driver: %s"
-               ", timer margin: %d seconds (nowayout=%d)"
-               ", allow kernel dump: %s (default = 0/OFF)"
-               ", priority: %s (default = 0/LAST).\n",
-               HPWDT_VERSION, soft_margin, nowayout,
-               (allow_kdump == 0) ? "OFF" : "ON",
-               (priority == 0) ? "LAST" : "FIRST");
-
+       dev_info(&dev->dev, "HP Watchdog Timer Driver: %s"
+                       ", timer margin: %d seconds (nowayout=%d).\n",
+                       HPWDT_VERSION, soft_margin, nowayout);
        return 0;
 
 error_misc_register:
-       unregister_die_notifier(&die_notifier);
-error_die_notifier:
-       if (cru_rom_addr)
-               iounmap(cru_rom_addr);
-error_get_cru:
+       hpwdt_exit_nmi_decoding();
+error_init_nmi_decoding:
        pci_iounmap(dev, pci_mem_addr);
 error_pci_iomap:
        pci_disable_device(dev);
@@ -768,10 +811,7 @@ static void __devexit hpwdt_exit(struct pci_dev *dev)
                hpwdt_stop();
 
        misc_deregister(&hpwdt_miscdev);
-       unregister_die_notifier(&die_notifier);
-
-       if (cru_rom_addr)
-               iounmap(cru_rom_addr);
+       hpwdt_exit_nmi_decoding();
        pci_iounmap(dev, pci_mem_addr);
        pci_disable_device(dev);
 }
@@ -802,16 +842,18 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 module_param(soft_margin, int, 0);
 MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
 
-module_param(allow_kdump, int, 0);
-MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
-
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+#ifdef CONFIG_HPWDT_NMI_DECODING
+module_param(allow_kdump, int, 0);
+MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
+
 module_param(priority, int, 0);
 MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last"
                " (default = 0/Last)\n");
+#endif /* !CONFIG_HPWDT_NMI_DECODING */
 
 module_init(hpwdt_init);
 module_exit(hpwdt_cleanup);
index ffea35c638799a4dcb7888e4c530afe1347190ab..0d5eeadf6121a23259c750490f46ef9c38d1d245 100644 (file)
@@ -31,21 +31,20 @@ static struct afs_cell *afs_cell_root;
  * allocate a cell record and fill in its name, VL server address list and
  * allocate an anonymous key
  */
-static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
+static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
+                                      char *vllist)
 {
        struct afs_cell *cell;
        struct key *key;
-       size_t namelen;
        char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
        char  *dvllist = NULL, *_vllist = NULL;
        char  delimiter = ':';
        int ret;
 
-       _enter("%s,%s", name, vllist);
+       _enter("%*.*s,%s", namelen, namelen, name ?: "", vllist);
 
        BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
 
-       namelen = strlen(name);
        if (namelen > AFS_MAXCELLNAME) {
                _leave(" = -ENAMETOOLONG");
                return ERR_PTR(-ENAMETOOLONG);
@@ -73,6 +72,10 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
        if (!vllist || strlen(vllist) < 7) {
                ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL);
                if (ret < 0) {
+                       if (ret == -ENODATA || ret == -EAGAIN || ret == -ENOKEY)
+                               /* translate these errors into something
+                                * userspace might understand */
+                               ret = -EDESTADDRREQ;
                        _leave(" = %d", ret);
                        return ERR_PTR(ret);
                }
@@ -138,26 +141,29 @@ error:
 }
 
 /*
- * create a cell record
- * - "name" is the name of the cell
- * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
+ * afs_cell_crate() - create a cell record
+ * @name:      is the name of the cell.
+ * @namsesz:   is the strlen of the cell name.
+ * @vllist:    is a colon separated list of IP addresses in "a.b.c.d" format.
+ * @retref:    is T to return the cell reference when the cell exists.
  */
-struct afs_cell *afs_cell_create(const char *name, char *vllist)
+struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
+                                char *vllist, bool retref)
 {
        struct afs_cell *cell;
        int ret;
 
-       _enter("%s,%s", name, vllist);
+       _enter("%*.*s,%s", namesz, namesz, name ?: "", vllist);
 
        down_write(&afs_cells_sem);
        read_lock(&afs_cells_lock);
        list_for_each_entry(cell, &afs_cells, link) {
-               if (strcasecmp(cell->name, name) == 0)
+               if (strncasecmp(cell->name, name, namesz) == 0)
                        goto duplicate_name;
        }
        read_unlock(&afs_cells_lock);
 
-       cell = afs_cell_alloc(name, vllist);
+       cell = afs_cell_alloc(name, namesz, vllist);
        if (IS_ERR(cell)) {
                _leave(" = %ld", PTR_ERR(cell));
                up_write(&afs_cells_sem);
@@ -197,8 +203,18 @@ error:
        return ERR_PTR(ret);
 
 duplicate_name:
+       if (retref && !IS_ERR(cell))
+               afs_get_cell(cell);
+
        read_unlock(&afs_cells_lock);
        up_write(&afs_cells_sem);
+
+       if (retref) {
+               _leave(" = %p", cell);
+               return cell;
+       }
+
+       _leave(" = -EEXIST");
        return ERR_PTR(-EEXIST);
 }
 
@@ -229,7 +245,7 @@ int afs_cell_init(char *rootcell)
                *cp++ = 0;
 
        /* allocate a cell record for the root cell */
-       new_root = afs_cell_create(rootcell, cp);
+       new_root = afs_cell_create(rootcell, strlen(rootcell), cp, false);
        if (IS_ERR(new_root)) {
                _leave(" = %ld", PTR_ERR(new_root));
                return PTR_ERR(new_root);
@@ -249,11 +265,12 @@ int afs_cell_init(char *rootcell)
 /*
  * lookup a cell record
  */
-struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
+struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
+                                bool dns_cell)
 {
        struct afs_cell *cell;
 
-       _enter("\"%*.*s\",", namesz, namesz, name ? name : "");
+       _enter("\"%*.*s\",", namesz, namesz, name ?: "");
 
        down_read(&afs_cells_sem);
        read_lock(&afs_cells_lock);
@@ -267,6 +284,8 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
                        }
                }
                cell = ERR_PTR(-ENOENT);
+               if (dns_cell)
+                       goto create_cell;
        found:
                ;
        } else {
@@ -289,6 +308,15 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
        up_read(&afs_cells_sem);
        _leave(" = %p", cell);
        return cell;
+
+create_cell:
+       read_unlock(&afs_cells_lock);
+       up_read(&afs_cells_sem);
+
+       cell = afs_cell_create(name, namesz, NULL, true);
+
+       _leave(" = %p", cell);
+       return cell;
 }
 
 #if 0
index b42d5cc1d6d21aace96eaae96fe3aa521822c7c9..0d38c09bd55e10f4eaf5f0e25ef11fa3d9d82919 100644 (file)
@@ -476,6 +476,40 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
        return 0;
 }
 
+/*
+ * Try to auto mount the mountpoint with pseudo directory, if the autocell
+ * operation is setted.
+ */
+static struct inode *afs_try_auto_mntpt(
+       int ret, struct dentry *dentry, struct inode *dir, struct key *key,
+       struct afs_fid *fid)
+{
+       const char *devname = dentry->d_name.name;
+       struct afs_vnode *vnode = AFS_FS_I(dir);
+       struct inode *inode;
+
+       _enter("%d, %p{%s}, {%x:%u}, %p",
+              ret, dentry, devname, vnode->fid.vid, vnode->fid.vnode, key);
+
+       if (ret != -ENOENT ||
+           !test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
+               goto out;
+
+       inode = afs_iget_autocell(dir, devname, strlen(devname), key);
+       if (IS_ERR(inode)) {
+               ret = PTR_ERR(inode);
+               goto out;
+       }
+
+       *fid = AFS_FS_I(inode)->fid;
+       _leave("= %p", inode);
+       return inode;
+
+out:
+       _leave("= %d", ret);
+       return ERR_PTR(ret);
+}
+
 /*
  * look up an entry in a directory
  */
@@ -520,6 +554,13 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 
        ret = afs_do_lookup(dir, dentry, &fid, key);
        if (ret < 0) {
+               inode = afs_try_auto_mntpt(ret, dentry, dir, key, &fid);
+               if (!IS_ERR(inode)) {
+                       key_put(key);
+                       goto success;
+               }
+
+               ret = PTR_ERR(inode);
                key_put(key);
                if (ret == -ENOENT) {
                        d_add(dentry, NULL);
@@ -539,6 +580,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_CAST(inode);
        }
 
+success:
        dentry->d_op = &afs_fs_dentry_operations;
 
        d_add(dentry, inode);
@@ -696,8 +738,9 @@ static int afs_d_delete(struct dentry *dentry)
                goto zap;
 
        if (dentry->d_inode &&
-           test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags))
-                       goto zap;
+           (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(dentry->d_inode)->flags) ||
+            test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(dentry->d_inode)->flags)))
+               goto zap;
 
        _leave(" = 0 [keep]");
        return 0;
index 320ffef115746362defa94edef14b3a083df64ae..0747339011c31261a1cd1e473db702395773e69b 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/sched.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
 #include "internal.h"
 
 struct afs_iget_data {
@@ -101,6 +103,16 @@ static int afs_iget5_test(struct inode *inode, void *opaque)
                inode->i_version == data->fid.unique;
 }
 
+/*
+ * iget5() comparator for inode created by autocell operations
+ *
+ * These pseudo inodes don't match anything.
+ */
+static int afs_iget5_autocell_test(struct inode *inode, void *opaque)
+{
+       return 0;
+}
+
 /*
  * iget5() inode initialiser
  */
@@ -117,6 +129,67 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
        return 0;
 }
 
+/*
+ * inode retrieval for autocell
+ */
+struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name,
+                               int namesz, struct key *key)
+{
+       struct afs_iget_data data;
+       struct afs_super_info *as;
+       struct afs_vnode *vnode;
+       struct super_block *sb;
+       struct inode *inode;
+       static atomic_t afs_autocell_ino;
+
+       _enter("{%x:%u},%*.*s,",
+              AFS_FS_I(dir)->fid.vid, AFS_FS_I(dir)->fid.vnode,
+              namesz, namesz, dev_name ?: "");
+
+       sb = dir->i_sb;
+       as = sb->s_fs_info;
+       data.volume = as->volume;
+       data.fid.vid = as->volume->vid;
+       data.fid.unique = 0;
+       data.fid.vnode = 0;
+
+       inode = iget5_locked(sb, atomic_inc_return(&afs_autocell_ino),
+                            afs_iget5_autocell_test, afs_iget5_set,
+                            &data);
+       if (!inode) {
+               _leave(" = -ENOMEM");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       _debug("GOT INODE %p { ino=%lu, vl=%x, vn=%x, u=%x }",
+              inode, inode->i_ino, data.fid.vid, data.fid.vnode,
+              data.fid.unique);
+
+       vnode = AFS_FS_I(inode);
+
+       /* there shouldn't be an existing inode */
+       BUG_ON(!(inode->i_state & I_NEW));
+
+       inode->i_size           = 0;
+       inode->i_mode           = S_IFDIR | S_IRUGO | S_IXUGO;
+       inode->i_op             = &afs_autocell_inode_operations;
+       inode->i_nlink          = 2;
+       inode->i_uid            = 0;
+       inode->i_gid            = 0;
+       inode->i_ctime.tv_sec   = get_seconds();
+       inode->i_ctime.tv_nsec  = 0;
+       inode->i_atime          = inode->i_mtime = inode->i_ctime;
+       inode->i_blocks         = 0;
+       inode->i_version        = 0;
+       inode->i_generation     = 0;
+
+       set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
+       inode->i_flags |= S_NOATIME;
+       unlock_new_inode(inode);
+       _leave(" = %p", inode);
+       return inode;
+}
+
 /*
  * inode retrieval
  */
@@ -313,6 +386,19 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        return 0;
 }
 
+/*
+ * discard an AFS inode
+ */
+int afs_drop_inode(struct inode *inode)
+{
+       _enter("");
+
+       if (test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(inode)->flags))
+               return generic_delete_inode(inode);
+       else
+               return generic_drop_inode(inode);
+}
+
 /*
  * clear an AFS inode
  */
index c6c93f180707b41e47d0101ee7188f34fed68927..cca8eef736fcf2b6f9a9516e96c4fc06c8d228be 100644 (file)
@@ -42,6 +42,7 @@ typedef enum {
 struct afs_mount_params {
        bool                    rwpath;         /* T if the parent should be considered R/W */
        bool                    force;          /* T to force cell type */
+       bool                    autocell;       /* T if set auto mount operation */
        afs_voltype_t           type;           /* type of volume requested */
        int                     volnamesz;      /* size of volume name */
        const char              *volname;       /* name of volume to mount */
@@ -358,6 +359,8 @@ struct afs_vnode {
 #define AFS_VNODE_READLOCKED   7               /* set if vnode is read-locked on the server */
 #define AFS_VNODE_WRITELOCKED  8               /* set if vnode is write-locked on the server */
 #define AFS_VNODE_UNLOCKING    9               /* set if vnode is being unlocked on the server */
+#define AFS_VNODE_AUTOCELL     10              /* set if Vnode is an auto mount point */
+#define AFS_VNODE_PSEUDODIR    11              /* set if Vnode is a pseudo directory */
 
        long                    acl_order;      /* ACL check count (callback break count) */
 
@@ -468,8 +471,8 @@ extern struct list_head afs_proc_cells;
 
 #define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
 extern int afs_cell_init(char *);
-extern struct afs_cell *afs_cell_create(const char *, char *);
-extern struct afs_cell *afs_cell_lookup(const char *, unsigned);
+extern struct afs_cell *afs_cell_create(const char *, unsigned, char *, bool);
+extern struct afs_cell *afs_cell_lookup(const char *, unsigned, bool);
 extern struct afs_cell *afs_grab_cell(struct afs_cell *);
 extern void afs_put_cell(struct afs_cell *);
 extern void afs_cell_purge(void);
@@ -558,6 +561,8 @@ extern int afs_fs_release_lock(struct afs_server *, struct key *,
 /*
  * inode.c
  */
+extern struct inode *afs_iget_autocell(struct inode *, const char *, int,
+                                      struct key *);
 extern struct inode *afs_iget(struct super_block *, struct key *,
                              struct afs_fid *, struct afs_file_status *,
                              struct afs_callback *);
@@ -566,6 +571,7 @@ extern int afs_validate(struct afs_vnode *, struct key *);
 extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int afs_setattr(struct dentry *, struct iattr *);
 extern void afs_evict_inode(struct inode *);
+extern int afs_drop_inode(struct inode *);
 
 /*
  * main.c
@@ -581,6 +587,7 @@ extern int afs_abort_to_error(u32);
  * mntpt.c
  */
 extern const struct inode_operations afs_mntpt_inode_operations;
+extern const struct inode_operations afs_autocell_inode_operations;
 extern const struct file_operations afs_mntpt_file_operations;
 
 extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
index a9e23039ea34604649156b66cd10dc664ece394a..6d552686c498fae427e2b9408bd03e96e1153699 100644 (file)
@@ -38,6 +38,11 @@ const struct inode_operations afs_mntpt_inode_operations = {
        .getattr        = afs_getattr,
 };
 
+const struct inode_operations afs_autocell_inode_operations = {
+       .follow_link    = afs_mntpt_follow_link,
+       .getattr        = afs_getattr,
+};
+
 static LIST_HEAD(afs_vfsmounts);
 static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
 
@@ -136,20 +141,16 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
 {
        struct afs_super_info *super;
        struct vfsmount *mnt;
+       struct afs_vnode *vnode;
        struct page *page;
-       size_t size;
-       char *buf, *devname, *options;
+       char *devname, *options;
+       bool rwpath = false;
        int ret;
 
        _enter("{%s}", mntpt->d_name.name);
 
        BUG_ON(!mntpt->d_inode);
 
-       ret = -EINVAL;
-       size = mntpt->d_inode->i_size;
-       if (size > PAGE_SIZE - 1)
-               goto error_no_devname;
-
        ret = -ENOMEM;
        devname = (char *) get_zeroed_page(GFP_KERNEL);
        if (!devname)
@@ -159,28 +160,59 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
        if (!options)
                goto error_no_options;
 
-       /* read the contents of the AFS special symlink */
-       page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
-       if (IS_ERR(page)) {
-               ret = PTR_ERR(page);
-               goto error_no_page;
+       vnode = AFS_FS_I(mntpt->d_inode);
+       if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
+               /* if the directory is a pseudo directory, use the d_name */
+               static const char afs_root_cell[] = ":root.cell.";
+               unsigned size = mntpt->d_name.len;
+
+               ret = -ENOENT;
+               if (size < 2 || size > AFS_MAXCELLNAME)
+                       goto error_no_page;
+
+               if (mntpt->d_name.name[0] == '.') {
+                       devname[0] = '#';
+                       memcpy(devname + 1, mntpt->d_name.name, size - 1);
+                       memcpy(devname + size, afs_root_cell,
+                              sizeof(afs_root_cell));
+                       rwpath = true;
+               } else {
+                       devname[0] = '%';
+                       memcpy(devname + 1, mntpt->d_name.name, size);
+                       memcpy(devname + size + 1, afs_root_cell,
+                              sizeof(afs_root_cell));
+               }
+       } else {
+               /* read the contents of the AFS special symlink */
+               loff_t size = i_size_read(mntpt->d_inode);
+               char *buf;
+
+               ret = -EINVAL;
+               if (size > PAGE_SIZE - 1)
+                       goto error_no_page;
+
+               page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
+               if (IS_ERR(page)) {
+                       ret = PTR_ERR(page);
+                       goto error_no_page;
+               }
+
+               ret = -EIO;
+               if (PageError(page))
+                       goto error;
+
+               buf = kmap_atomic(page, KM_USER0);
+               memcpy(devname, buf, size);
+               kunmap_atomic(buf, KM_USER0);
+               page_cache_release(page);
+               page = NULL;
        }
 
-       ret = -EIO;
-       if (PageError(page))
-               goto error;
-
-       buf = kmap_atomic(page, KM_USER0);
-       memcpy(devname, buf, size);
-       kunmap_atomic(buf, KM_USER0);
-       page_cache_release(page);
-       page = NULL;
-
        /* work out what options we want */
        super = AFS_FS_S(mntpt->d_sb);
        memcpy(options, "cell=", 5);
        strcpy(options + 5, super->volume->cell->name);
-       if (super->volume->type == AFSVL_RWVOL)
+       if (super->volume->type == AFSVL_RWVOL || rwpath)
                strcat(options, ",rwpath");
 
        /* try and do the mount */
index 852739d262a9f7eecff472d33845adb2a0a310f0..096b23f821a1081a2370df2de59276c9d08b807f 100644 (file)
@@ -294,7 +294,7 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
        if (strcmp(kbuf, "add") == 0) {
                struct afs_cell *cell;
 
-               cell = afs_cell_create(name, args);
+               cell = afs_cell_create(name, strlen(name), args, false);
                if (IS_ERR(cell)) {
                        ret = PTR_ERR(cell);
                        goto done;
index 9cf80f02da16a119747eb314ace489e50b1aaabf..77e1e5a61154c6796d80d709ed31722017d90e18 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
@@ -48,6 +49,7 @@ struct file_system_type afs_fs_type = {
 static const struct super_operations afs_super_ops = {
        .statfs         = afs_statfs,
        .alloc_inode    = afs_alloc_inode,
+       .drop_inode     = afs_drop_inode,
        .destroy_inode  = afs_destroy_inode,
        .evict_inode    = afs_evict_inode,
        .put_super      = afs_put_super,
@@ -62,12 +64,14 @@ enum {
        afs_opt_cell,
        afs_opt_rwpath,
        afs_opt_vol,
+       afs_opt_autocell,
 };
 
 static const match_table_t afs_options_list = {
        { afs_opt_cell,         "cell=%s"       },
        { afs_opt_rwpath,       "rwpath"        },
        { afs_opt_vol,          "vol=%s"        },
+       { afs_opt_autocell,     "autocell"      },
        { afs_no_opt,           NULL            },
 };
 
@@ -151,7 +155,8 @@ static int afs_parse_options(struct afs_mount_params *params,
                switch (token) {
                case afs_opt_cell:
                        cell = afs_cell_lookup(args[0].from,
-                                              args[0].to - args[0].from);
+                                              args[0].to - args[0].from,
+                                              false);
                        if (IS_ERR(cell))
                                return PTR_ERR(cell);
                        afs_put_cell(params->cell);
@@ -166,6 +171,10 @@ static int afs_parse_options(struct afs_mount_params *params,
                        *devname = args[0].from;
                        break;
 
+               case afs_opt_autocell:
+                       params->autocell = 1;
+                       break;
+
                default:
                        printk(KERN_ERR "kAFS:"
                               " Unknown or invalid mount option: '%s'\n", p);
@@ -252,10 +261,10 @@ static int afs_parse_device_name(struct afs_mount_params *params,
 
        /* lookup the cell record */
        if (cellname || !params->cell) {
-               cell = afs_cell_lookup(cellname, cellnamesz);
+               cell = afs_cell_lookup(cellname, cellnamesz, true);
                if (IS_ERR(cell)) {
-                       printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
-                              cellname ?: "");
+                       printk(KERN_ERR "kAFS: unable to lookup cell '%*.*s'\n",
+                              cellnamesz, cellnamesz, cellname ?: "");
                        return PTR_ERR(cell);
                }
                afs_put_cell(params->cell);
@@ -321,6 +330,9 @@ static int afs_fill_super(struct super_block *sb, void *data)
        if (IS_ERR(inode))
                goto error_inode;
 
+       if (params->autocell)
+               set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
+
        ret = -ENOMEM;
        root = d_alloc_root(inode);
        if (!root)
index 52e59bf4aa5f512f365d509768984fa95b7d62f0..f024d8aaddefff929ec7d557fdfc6449ab7825b8 100644 (file)
@@ -55,12 +55,6 @@ static unsigned int bad_file_poll(struct file *filp, poll_table *wait)
        return POLLERR;
 }
 
-static int bad_file_ioctl (struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg)
-{
-       return -EIO;
-}
-
 static long bad_file_unlocked_ioctl(struct file *file, unsigned cmd,
                        unsigned long arg)
 {
@@ -159,7 +153,6 @@ static const struct file_operations bad_file_ops =
        .aio_write      = bad_file_aio_write,
        .readdir        = bad_file_readdir,
        .poll           = bad_file_poll,
-       .ioctl          = bad_file_ioctl,
        .unlocked_ioctl = bad_file_unlocked_ioctl,
        .compat_ioctl   = bad_file_compat_ioctl,
        .mmap           = bad_file_mmap,
index a7081eeeb85d08729588f653469a7bf3f1dac8e2..7099a526f775d24325c7d2c6ebd213faf1d6d87c 100644 (file)
@@ -301,6 +301,16 @@ A partial list of the supported mount options follows:
   gid          Set the default gid for inodes (similar to above).
   file_mode     If CIFS Unix extensions are not supported by the server
                this overrides the default mode for file inodes.
+  fsc          Enable local disk caching using FS-Cache (off by default). This
+               option could be useful to improve performance on a slow link,
+               heavily loaded server and/or network where reading from the
+               disk is faster than reading from the server (over the network).
+               This could also impact scalability positively as the
+               number of calls to the server are reduced. However, local
+               caching is not suitable for all workloads for e.g. read-once
+               type workloads. So, you need to consider carefully your
+               workload/scenario before using this option. Currently, local
+               disk caching is functional for CIFS files opened as read-only.
   dir_mode      If CIFS Unix extensions are not supported by the server 
                this overrides the default mode for directory inodes.
   port         attempt to contact the server on this tcp port, before
index e6d5d70cf3cf6dbc78982d2a1ade3c18bc564366..718c7062aec129844cda361e2f4b8a143aa31861 100644 (file)
@@ -77,7 +77,8 @@ int compat_printk(const char *fmt, ...)
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
  */
-asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t)
+asmlinkage long compat_sys_utime(const char __user *filename,
+                                struct compat_utimbuf __user *t)
 {
        struct timespec tv[2];
 
@@ -91,7 +92,7 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __
        return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
 }
 
-asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags)
+asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags)
 {
        struct timespec tv[2];
 
@@ -106,7 +107,7 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, st
        return do_utimes(dfd, filename, t ? tv : NULL, flags);
 }
 
-asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t)
+asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct compat_timeval __user *t)
 {
        struct timespec tv[2];
 
@@ -125,7 +126,7 @@ asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, st
        return do_utimes(dfd, filename, t ? tv : NULL, 0);
 }
 
-asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
+asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_timeval __user *t)
 {
        return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
@@ -169,7 +170,7 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
        return err;
 }
 
-asmlinkage long compat_sys_newstat(char __user * filename,
+asmlinkage long compat_sys_newstat(const char __user * filename,
                struct compat_stat __user *statbuf)
 {
        struct kstat stat;
@@ -181,7 +182,7 @@ asmlinkage long compat_sys_newstat(char __user * filename,
        return cp_compat_stat(&stat, statbuf);
 }
 
-asmlinkage long compat_sys_newlstat(char __user * filename,
+asmlinkage long compat_sys_newlstat(const char __user * filename,
                struct compat_stat __user *statbuf)
 {
        struct kstat stat;
@@ -194,7 +195,8 @@ asmlinkage long compat_sys_newlstat(char __user * filename,
 }
 
 #ifndef __ARCH_WANT_STAT64
-asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
+asmlinkage long compat_sys_newfstatat(unsigned int dfd,
+               const char __user *filename,
                struct compat_stat __user *statbuf, int flag)
 {
        struct kstat stat;
@@ -837,9 +839,10 @@ static int do_nfs4_super_data_conv(void *raw_data)
 #define NCPFS_NAME      "ncpfs"
 #define NFS4_NAME      "nfs4"
 
-asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
-                                char __user * type, unsigned long flags,
-                                void __user * data)
+asmlinkage long compat_sys_mount(const char __user * dev_name,
+                                const char __user * dir_name,
+                                const char __user * type, unsigned long flags,
+                                const void __user * data)
 {
        char *kernel_type;
        unsigned long data_page;
index 70227e0dc01d4caa1165b3371a6d28e6a8690a61..03e59aa318eb0a2c9801857a9d343fa008fdc7a2 100644 (file)
@@ -1699,8 +1699,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
                                goto out_fput;
                }
 
-               if (!filp->f_op ||
-                   (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
+               if (!filp->f_op || !filp->f_op->unlocked_ioctl)
                        goto do_ioctl;
                break;
        }
index 2d140a713861badfb1c9b936c683805dab30853a..f855ea4fc88895a13b53b075b9a3fb0dbcb53d8b 100644 (file)
@@ -29,7 +29,6 @@
  * @arg:       command-specific argument for ioctl
  *
  * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
- * invokes filesystem specific ->ioctl method.  If neither method exists,
  * returns -ENOTTY.
  *
  * Returns 0 on success, -errno on error.
@@ -39,21 +38,12 @@ static long vfs_ioctl(struct file *filp, unsigned int cmd,
 {
        int error = -ENOTTY;
 
-       if (!filp->f_op)
+       if (!filp->f_op || !filp->f_op->unlocked_ioctl)
                goto out;
 
-       if (filp->f_op->unlocked_ioctl) {
-               error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
-               if (error == -ENOIOCTLCMD)
-                       error = -EINVAL;
-               goto out;
-       } else if (filp->f_op->ioctl) {
-               lock_kernel();
-               error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
-                                         filp, cmd, arg);
-               unlock_kernel();
-       }
-
+       error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
+       if (error == -ENOIOCTLCMD)
+               error = -EINVAL;
  out:
        return error;
 }
index 675cc49197feb177bcb67e0f0aefa66deed9cabd..9777eb5b552248410bd3331f97fb89e853149866 100644 (file)
@@ -824,7 +824,7 @@ const struct inode_operations logfs_dir_iops = {
 };
 const struct file_operations logfs_dir_fops = {
        .fsync          = logfs_fsync,
-       .ioctl          = logfs_ioctl,
+       .unlocked_ioctl = logfs_ioctl,
        .readdir        = logfs_readdir,
        .read           = generic_read_dir,
 };
index 4dd0f7c06e394e1a43b323f95f29784718a0ab9c..e86376b87af11d26034188df8d3c2da2bc469587 100644 (file)
@@ -181,9 +181,9 @@ static int logfs_releasepage(struct page *page, gfp_t only_xfs_uses_this)
 }
 
 
-int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-               unsigned long arg)
+long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct logfs_inode *li = logfs_inode(inode);
        unsigned int oldflags, flags;
        int err;
@@ -255,7 +255,7 @@ const struct file_operations logfs_reg_fops = {
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
        .fsync          = logfs_fsync,
-       .ioctl          = logfs_ioctl,
+       .unlocked_ioctl = logfs_ioctl,
        .llseek         = generic_file_llseek,
        .mmap           = generic_file_readonly_mmap,
        .open           = generic_file_open,
index 5e3b720779516d8ec6d8c74794c57c861a5436d5..b8786264d243fcd49d31f9d3fe670657264e46d4 100644 (file)
@@ -504,8 +504,7 @@ extern const struct inode_operations logfs_reg_iops;
 extern const struct file_operations logfs_reg_fops;
 extern const struct address_space_operations logfs_reg_aops;
 int logfs_readpage(struct file *file, struct page *page);
-int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-               unsigned long arg);
+long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 int logfs_fsync(struct file *file, int datasync);
 
 /* gc.c */
index cc1bb33b59b8d919b64c3b8c2895c3b08c6d80f5..26a510a7be0908023eaa5848002eced097f6e9dc 100644 (file)
@@ -100,3 +100,20 @@ config NFS_FSCACHE
        help
          Say Y here if you want NFS data to be cached locally on disc through
          the general filesystem cache manager
+
+config NFS_USE_LEGACY_DNS
+       bool "Use the legacy NFS DNS resolver"
+       depends on NFS_V4
+       help
+         The kernel now provides a method for translating a host name into an
+         IP address.  Select Y here if you would rather use your own DNS
+         resolver script.
+
+         If unsure, say N
+
+config NFS_USE_KERNEL_DNS
+       bool
+       depends on NFS_V4 && !NFS_USE_LEGACY_DNS
+       select DNS_RESOLVER
+       select KEYS
+       default y
index 76fd235d0024e1970d44044536d2d929c02b9256..dba50a5625db7987d1e4a757063f3a5412ff5928 100644 (file)
@@ -6,6 +6,29 @@
  * Resolves DNS hostnames into valid ip addresses
  */
 
+#ifdef CONFIG_NFS_USE_KERNEL_DNS
+
+#include <linux/sunrpc/clnt.h>
+#include <linux/dns_resolver.h>
+
+ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
+               struct sockaddr *sa, size_t salen)
+{
+       ssize_t ret;
+       char *ip_addr = NULL;
+       int ip_len;
+
+       ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL);
+       if (ip_len > 0)
+               ret = rpc_pton(ip_addr, ip_len, sa, salen);
+       else
+               ret = -ESRCH;
+       kfree(ip_addr);
+       return ret;
+}
+
+#else
+
 #include <linux/hash.h>
 #include <linux/string.h>
 #include <linux/kmod.h>
@@ -346,3 +369,4 @@ void nfs_dns_resolver_destroy(void)
        nfs_cache_unregister(&nfs_dns_resolve);
 }
 
+#endif
index a3f0938babf7685360fcb43bf84e29c8fcfc8e5b..199bb5543a91ad3dfc1e03e2f85894f78661e4cb 100644 (file)
@@ -6,8 +6,20 @@
 
 #define NFS_DNS_HOSTNAME_MAXLEN        (128)
 
+
+#ifdef CONFIG_NFS_USE_KERNEL_DNS
+static inline int nfs_dns_resolver_init(void)
+{
+       return 0;
+}
+
+static inline void nfs_dns_resolver_destroy(void)
+{}
+#else
 extern int nfs_dns_resolver_init(void);
 extern void nfs_dns_resolver_destroy(void);
+#endif
+
 extern ssize_t nfs_dns_resolve_name(char *name, size_t namelen,
                struct sockaddr *sa, size_t salen);
 
index da702294d7e75b1e995fcd0c73a6562e264a3561..a76e0aa5cd3fc5188a392639618858a7e7e34092 100644 (file)
@@ -290,12 +290,30 @@ static int ocfs2_set_acl(handle_t *handle,
 
 int ocfs2_check_acl(struct inode *inode, int mask)
 {
-       struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct buffer_head *di_bh = NULL;
+       struct posix_acl *acl;
+       int ret = -EAGAIN;
 
-       if (IS_ERR(acl))
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return ret;
+
+       ret = ocfs2_read_inode_block(inode, &di_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh);
+
+       brelse(di_bh);
+
+       if (IS_ERR(acl)) {
+               mlog_errno(PTR_ERR(acl));
                return PTR_ERR(acl);
+       }
        if (acl) {
-               int ret = posix_acl_permission(inode, acl, mask);
+               ret = posix_acl_permission(inode, acl, mask);
                posix_acl_release(acl);
                return ret;
        }
@@ -344,7 +362,7 @@ int ocfs2_init_acl(handle_t *handle,
 {
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct posix_acl *acl = NULL;
-       int ret = 0;
+       int ret = 0, ret2;
        mode_t mode;
 
        if (!S_ISLNK(inode->i_mode)) {
@@ -381,7 +399,12 @@ int ocfs2_init_acl(handle_t *handle,
                mode = inode->i_mode;
                ret = posix_acl_create_masq(clone, &mode);
                if (ret >= 0) {
-                       ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+                       ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+                       if (ret2) {
+                               mlog_errno(ret2);
+                               ret = ret2;
+                               goto cleanup;
+                       }
                        if (ret > 0) {
                                ret = ocfs2_set_acl(handle, inode,
                                                    di_bh, ACL_TYPE_ACCESS,
index aa75ca3f78dabd9a73921df967bc5e4efeb41d9a..1361997cf205d132a04ddeb87760aa233c3e707d 100644 (file)
@@ -1759,6 +1759,7 @@ static int o2net_accept_one(struct socket *sock)
        struct sockaddr_in sin;
        struct socket *new_sock = NULL;
        struct o2nm_node *node = NULL;
+       struct o2nm_node *local_node = NULL;
        struct o2net_sock_container *sc = NULL;
        struct o2net_node *nn;
 
@@ -1796,11 +1797,15 @@ static int o2net_accept_one(struct socket *sock)
                goto out;
        }
 
-       if (o2nm_this_node() > node->nd_num) {
-               mlog(ML_NOTICE, "unexpected connect attempted from a lower "
-                    "numbered node '%s' at " "%pI4:%d with num %u\n",
-                    node->nd_name, &sin.sin_addr.s_addr,
-                    ntohs(sin.sin_port), node->nd_num);
+       if (o2nm_this_node() >= node->nd_num) {
+               local_node = o2nm_get_node_by_num(o2nm_this_node());
+               mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' ("
+                    "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n",
+                    local_node->nd_name, local_node->nd_num,
+                    &(local_node->nd_ipv4_address),
+                    ntohs(local_node->nd_ipv4_port),
+                    node->nd_name, node->nd_num, &sin.sin_addr.s_addr,
+                    ntohs(sin.sin_port));
                ret = -EINVAL;
                goto out;
        }
@@ -1857,6 +1862,8 @@ out:
                sock_release(new_sock);
        if (node)
                o2nm_node_put(node);
+       if (local_node)
+               o2nm_node_put(local_node);
        if (sc)
                sc_put(sc);
        return ret;
index 94b97fc6a88e62522b1958ed6a89de5e6803525b..ffb4c68dafa495bc739165eb30f718f1eb0865ec 100644 (file)
@@ -511,8 +511,6 @@ static void dlm_lockres_release(struct kref *kref)
 
        atomic_dec(&dlm->res_cur_count);
 
-       dlm_put(dlm);
-
        if (!hlist_unhashed(&res->hash_node) ||
            !list_empty(&res->granted) ||
            !list_empty(&res->converting) ||
@@ -585,8 +583,6 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
        res->migration_pending = 0;
        res->inflight_locks = 0;
 
-       /* put in dlm_lockres_release */
-       dlm_grab(dlm);
        res->dlm = dlm;
 
        kref_init(&res->refs);
@@ -3050,8 +3046,6 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
        /* check for pre-existing lock */
        spin_lock(&dlm->spinlock);
        res = __dlm_lookup_lockres(dlm, name, namelen, hash);
-       spin_lock(&dlm->master_lock);
-
        if (res) {
                spin_lock(&res->spinlock);
                if (res->state & DLM_LOCK_RES_RECOVERING) {
@@ -3069,14 +3063,15 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
                spin_unlock(&res->spinlock);
        }
 
+       spin_lock(&dlm->master_lock);
        /* ignore status.  only nonzero status would BUG. */
        ret = dlm_add_migration_mle(dlm, res, mle, &oldmle,
                                    name, namelen,
                                    migrate->new_master,
                                    migrate->master);
 
-unlock:
        spin_unlock(&dlm->master_lock);
+unlock:
        spin_unlock(&dlm->spinlock);
 
        if (oldmle) {
index 9dfaac73b36da4350cc5a2f2dc7a34918a21e11e..aaaffbcbe9163f0ea7376301bc854d85a0bd5b66 100644 (file)
@@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
        struct list_head *queue;
        struct dlm_lock *lock, *next;
 
+       assert_spin_locked(&dlm->spinlock);
+       assert_spin_locked(&res->spinlock);
        res->state |= DLM_LOCK_RES_RECOVERING;
        if (!list_empty(&res->recovering)) {
                mlog(0,
@@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
                        /* zero the lvb if necessary */
                        dlm_revalidate_lvb(dlm, res, dead_node);
                        if (res->owner == dead_node) {
-                               if (res->state & DLM_LOCK_RES_DROPPING_REF)
-                                       mlog(0, "%s:%.*s: owned by "
-                                            "dead node %u, this node was "
-                                            "dropping its ref when it died. "
-                                            "continue, dropping the flag.\n",
-                                            dlm->name, res->lockname.len,
-                                            res->lockname.name, dead_node);
-
-                               /* the wake_up for this will happen when the
-                                * RECOVERING flag is dropped later */
-                               res->state &= ~DLM_LOCK_RES_DROPPING_REF;
+                               if (res->state & DLM_LOCK_RES_DROPPING_REF) {
+                                       mlog(ML_NOTICE, "Ignore %.*s for "
+                                            "recovery as it is being freed\n",
+                                            res->lockname.len,
+                                            res->lockname.name);
+                               } else
+                                       dlm_move_lockres_to_recovery_list(dlm,
+                                                                         res);
 
-                               dlm_move_lockres_to_recovery_list(dlm, res);
                        } else if (res->owner == dlm->node_num) {
                                dlm_free_dead_locks(dlm, res, dead_node);
                                __dlm_lockres_calc_usage(dlm, res);
index d4f73ca68fe5c325b0b768024dd84db1e1062a59..2211acf33d9b9be5937ca86c633cd72c013ffd2d 100644 (file)
@@ -92,19 +92,27 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
  * truly ready to be freed. */
 int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
-       if (!__dlm_lockres_has_locks(res) &&
-           (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) {
-               /* try not to scan the bitmap unless the first two
-                * conditions are already true */
-               int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
-               if (bit >= O2NM_MAX_NODES) {
-                       /* since the bit for dlm->node_num is not
-                        * set, inflight_locks better be zero */
-                       BUG_ON(res->inflight_locks != 0);
-                       return 1;
-               }
-       }
-       return 0;
+       int bit;
+
+       if (__dlm_lockres_has_locks(res))
+               return 0;
+
+       if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
+               return 0;
+
+       if (res->state & DLM_LOCK_RES_RECOVERING)
+               return 0;
+
+       bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
+       if (bit < O2NM_MAX_NODES)
+               return 0;
+
+       /*
+        * since the bit for dlm->node_num is not set, inflight_locks better
+        * be zero
+        */
+       BUG_ON(res->inflight_locks != 0);
+       return 1;
 }
 
 
@@ -152,45 +160,25 @@ void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
        spin_unlock(&dlm->spinlock);
 }
 
-static int dlm_purge_lockres(struct dlm_ctxt *dlm,
+static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                             struct dlm_lock_resource *res)
 {
        int master;
        int ret = 0;
 
-       spin_lock(&res->spinlock);
-       if (!__dlm_lockres_unused(res)) {
-               mlog(0, "%s:%.*s: tried to purge but not unused\n",
-                    dlm->name, res->lockname.len, res->lockname.name);
-               __dlm_print_one_lock_resource(res);
-               spin_unlock(&res->spinlock);
-               BUG();
-       }
-
-       if (res->state & DLM_LOCK_RES_MIGRATING) {
-               mlog(0, "%s:%.*s: Delay dropref as this lockres is "
-                    "being remastered\n", dlm->name, res->lockname.len,
-                    res->lockname.name);
-               /* Re-add the lockres to the end of the purge list */
-               if (!list_empty(&res->purge)) {
-                       list_del_init(&res->purge);
-                       list_add_tail(&res->purge, &dlm->purge_list);
-               }
-               spin_unlock(&res->spinlock);
-               return 0;
-       }
+       assert_spin_locked(&dlm->spinlock);
+       assert_spin_locked(&res->spinlock);
 
        master = (res->owner == dlm->node_num);
 
-       if (!master)
-               res->state |= DLM_LOCK_RES_DROPPING_REF;
-       spin_unlock(&res->spinlock);
 
        mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len,
             res->lockname.name, master);
 
        if (!master) {
+               res->state |= DLM_LOCK_RES_DROPPING_REF;
                /* drop spinlock...  retake below */
+               spin_unlock(&res->spinlock);
                spin_unlock(&dlm->spinlock);
 
                spin_lock(&res->spinlock);
@@ -208,31 +196,35 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
                mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n",
                     dlm->name, res->lockname.len, res->lockname.name, ret);
                spin_lock(&dlm->spinlock);
+               spin_lock(&res->spinlock);
        }
 
-       spin_lock(&res->spinlock);
        if (!list_empty(&res->purge)) {
                mlog(0, "removing lockres %.*s:%p from purgelist, "
                     "master = %d\n", res->lockname.len, res->lockname.name,
                     res, master);
                list_del_init(&res->purge);
-               spin_unlock(&res->spinlock);
                dlm_lockres_put(res);
                dlm->purge_count--;
-       } else
-               spin_unlock(&res->spinlock);
+       }
+
+       if (!__dlm_lockres_unused(res)) {
+               mlog(ML_ERROR, "found lockres %s:%.*s: in use after deref\n",
+                    dlm->name, res->lockname.len, res->lockname.name);
+               __dlm_print_one_lock_resource(res);
+               BUG();
+       }
 
        __dlm_unhash_lockres(res);
 
        /* lockres is not in the hash now.  drop the flag and wake up
         * any processes waiting in dlm_get_lock_resource. */
        if (!master) {
-               spin_lock(&res->spinlock);
                res->state &= ~DLM_LOCK_RES_DROPPING_REF;
                spin_unlock(&res->spinlock);
                wake_up(&res->wq);
-       }
-       return 0;
+       } else
+               spin_unlock(&res->spinlock);
 }
 
 static void dlm_run_purge_list(struct dlm_ctxt *dlm,
@@ -251,17 +243,7 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
                lockres = list_entry(dlm->purge_list.next,
                                     struct dlm_lock_resource, purge);
 
-               /* Status of the lockres *might* change so double
-                * check. If the lockres is unused, holding the dlm
-                * spinlock will prevent people from getting and more
-                * refs on it -- there's no need to keep the lockres
-                * spinlock. */
                spin_lock(&lockres->spinlock);
-               unused = __dlm_lockres_unused(lockres);
-               spin_unlock(&lockres->spinlock);
-
-               if (!unused)
-                       continue;
 
                purge_jiffies = lockres->last_used +
                        msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);
@@ -273,15 +255,29 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
                         * in tail order, we can stop at the first
                         * unpurgable resource -- anyone added after
                         * him will have a greater last_used value */
+                       spin_unlock(&lockres->spinlock);
                        break;
                }
 
+               /* Status of the lockres *might* change so double
+                * check. If the lockres is unused, holding the dlm
+                * spinlock will prevent people from getting and more
+                * refs on it. */
+               unused = __dlm_lockres_unused(lockres);
+               if (!unused ||
+                   (lockres->state & DLM_LOCK_RES_MIGRATING)) {
+                       mlog(0, "lockres %s:%.*s: is in use or "
+                            "being remastered, used %d, state %d\n",
+                            dlm->name, lockres->lockname.len,
+                            lockres->lockname.name, !unused, lockres->state);
+                       list_move_tail(&dlm->purge_list, &lockres->purge);
+                       spin_unlock(&lockres->spinlock);
+                       continue;
+               }
+
                dlm_lockres_get(lockres);
 
-               /* This may drop and reacquire the dlm spinlock if it
-                * has to do migration. */
-               if (dlm_purge_lockres(dlm, lockres))
-                       BUG();
+               dlm_purge_lockres(dlm, lockres);
 
                dlm_lockres_put(lockres);
 
index 3ac5aa733e9c8018090bc2493d819937593760a0..73a11ccfd4c280681abe672c5e9cd81e3b229a93 100644 (file)
@@ -2436,16 +2436,26 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
                len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) +
                          le32_to_cpu(rec.r_clusters)) - cpos;
                /*
-                * If the refcount rec already exist, cool. We just need
-                * to check whether there is a split. Otherwise we just need
-                * to increase the refcount.
-                * If we will insert one, increases recs_add.
-                *
                 * We record all the records which will be inserted to the
                 * same refcount block, so that we can tell exactly whether
                 * we need a new refcount block or not.
+                *
+                * If we will insert a new one, this is easy and only happens
+                * during adding refcounted flag to the extent, so we don't
+                * have a chance of spliting. We just need one record.
+                *
+                * If the refcount rec already exists, that would be a little
+                * complicated. we may have to:
+                * 1) split at the beginning if the start pos isn't aligned.
+                *    we need 1 more record in this case.
+                * 2) split int the end if the end pos isn't aligned.
+                *    we need 1 more record in this case.
+                * 3) split in the middle because of file system fragmentation.
+                *    we need 2 more records in this case(we can't detect this
+                *    beforehand, so always think of the worst case).
                 */
                if (rec.r_refcount) {
+                       recs_add += 2;
                        /* Check whether we need a split at the beginning. */
                        if (cpos == start_cpos &&
                            cpos != le64_to_cpu(rec.r_cpos))
index d1b8a5c4bc0aa556f1eff3183d1a49530bbc0da1..d513a07f44bb54805de9adf7171c0991aa4ab309 100644 (file)
@@ -182,7 +182,7 @@ int ibm_partition(struct parsed_partitions *state)
                                offset = (info->label_block + 1);
                        } else {
                                /* unlabeled disk */
-                               strlcat(tmp, sizeof(tmp), "(nonl)", PAGE_SIZE);
+                               strlcat(state->pp_buf, "(nonl)", PAGE_SIZE);
                                size = i_size >> 9;
                                offset = (info->label_block + 1);
                        }
index 23561cda7245432bc132a8e7f5c50c62dc75aa84..9c2b5f484879ad37a1633a6023524e2cb0151a3f 100644 (file)
@@ -214,8 +214,7 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
 {
        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        long rv = -ENOTTY;
-       long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
-       int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
+       long (*ioctl)(struct file *, unsigned int, unsigned long);
 
        spin_lock(&pde->pde_unload_lock);
        if (!pde->proc_fops) {
@@ -223,19 +222,11 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
                return rv;
        }
        pde->pde_users++;
-       unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
-       ioctl = pde->proc_fops->ioctl;
+       ioctl = pde->proc_fops->unlocked_ioctl;
        spin_unlock(&pde->pde_unload_lock);
 
-       if (unlocked_ioctl) {
-               rv = unlocked_ioctl(file, cmd, arg);
-               if (rv == -ENOIOCTLCMD)
-                       rv = -EINVAL;
-       } else if (ioctl) {
-               WARN_ONCE(1, "Procfs ioctl handlers must use unlocked_ioctl, "
-                         "%pf will be called without the Bkl held\n", ioctl);
-               rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
-       }
+       if (ioctl)
+               rv = ioctl(file, cmd, arg);
 
        pde_users_dec(pde);
        return rv;
index c4ecd52c5737b5aeb8c8bfd671d05b8a76f995a8..12e90e213900542291a0fa74da940c0588b69ace 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -68,7 +68,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
 }
 EXPORT_SYMBOL(vfs_fstat);
 
-int vfs_fstatat(int dfd, char __user *filename, struct kstat *stat, int flag)
+int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
+               int flag)
 {
        struct path path;
        int error = -EINVAL;
@@ -91,13 +92,13 @@ out:
 }
 EXPORT_SYMBOL(vfs_fstatat);
 
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_stat(const char __user *name, struct kstat *stat)
 {
        return vfs_fstatat(AT_FDCWD, name, stat, 0);
 }
 EXPORT_SYMBOL(vfs_stat);
 
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_lstat(const char __user *name, struct kstat *stat)
 {
        return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
 }
@@ -147,7 +148,8 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
+SYSCALL_DEFINE2(stat, const char __user *, filename,
+               struct __old_kernel_stat __user *, statbuf)
 {
        struct kstat stat;
        int error;
@@ -159,7 +161,8 @@ SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *
        return cp_old_stat(&stat, statbuf);
 }
 
-SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
+SYSCALL_DEFINE2(lstat, const char __user *, filename,
+               struct __old_kernel_stat __user *, statbuf)
 {
        struct kstat stat;
        int error;
@@ -234,7 +237,8 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf)
+SYSCALL_DEFINE2(newstat, const char __user *, filename,
+               struct stat __user *, statbuf)
 {
        struct kstat stat;
        int error = vfs_stat(filename, &stat);
@@ -244,7 +248,8 @@ SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf)
        return cp_new_stat(&stat, statbuf);
 }
 
-SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf)
+SYSCALL_DEFINE2(newlstat, const char __user *, filename,
+               struct stat __user *, statbuf)
 {
        struct kstat stat;
        int error;
@@ -257,7 +262,7 @@ SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf
 }
 
 #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
-SYSCALL_DEFINE4(newfstatat, int, dfd, char __user *, filename,
+SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
                struct stat __user *, statbuf, int, flag)
 {
        struct kstat stat;
@@ -355,7 +360,8 @@ static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-SYSCALL_DEFINE2(stat64, char __user *, filename, struct stat64 __user *, statbuf)
+SYSCALL_DEFINE2(stat64, const char __user *, filename,
+               struct stat64 __user *, statbuf)
 {
        struct kstat stat;
        int error = vfs_stat(filename, &stat);
@@ -366,7 +372,8 @@ SYSCALL_DEFINE2(stat64, char __user *, filename, struct stat64 __user *, statbuf
        return error;
 }
 
-SYSCALL_DEFINE2(lstat64, char __user *, filename, struct stat64 __user *, statbuf)
+SYSCALL_DEFINE2(lstat64, const char __user *, filename,
+               struct stat64 __user *, statbuf)
 {
        struct kstat stat;
        int error = vfs_lstat(filename, &stat);
@@ -388,7 +395,7 @@ SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
        return error;
 }
 
-SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename,
+SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
                struct stat64 __user *, statbuf, int, flag)
 {
        struct kstat stat;
index e4c75db5d373cbbc8f98f0bdb8167ff00fbda7fb..179b586906573a444561a892e906d2f5b02963e8 100644 (file)
@@ -126,7 +126,8 @@ out:
  * must be owner or have write permission.
  * Else, update from *times, must be owner or super user.
  */
-long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags)
+long do_utimes(int dfd, const char __user *filename, struct timespec *times,
+              int flags)
 {
        int error = -EINVAL;
 
@@ -170,7 +171,7 @@ out:
        return error;
 }
 
-SYSCALL_DEFINE4(utimensat, int, dfd, char __user *, filename,
+SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
                struct timespec __user *, utimes, int, flags)
 {
        struct timespec tstimes[2];
@@ -188,7 +189,7 @@ SYSCALL_DEFINE4(utimensat, int, dfd, char __user *, filename,
        return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags);
 }
 
-SYSCALL_DEFINE3(futimesat, int, dfd, char __user *, filename,
+SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
                struct timeval __user *, utimes)
 {
        struct timeval times[2];
index 168f7daa7bdeb8d05e30895a82460310b6924dce..9ddc8780e8db7bfe45496587bc47e5fb00d12073 100644 (file)
@@ -331,7 +331,7 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
                        const compat_sigset_t __user *sigmask,
                        compat_size_t sigsetsize);
 
-asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename,
+asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename,
                                struct compat_timespec __user *t, int flags);
 
 asmlinkage long compat_sys_signalfd(int ufd,
@@ -348,9 +348,9 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page,
                                      const int __user *nodes,
                                      int __user *status,
                                      int flags);
-asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,
+asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename,
                                     struct compat_timeval __user *t);
-asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
+asmlinkage long compat_sys_newfstatat(unsigned int dfd, const char __user * filename,
                                      struct compat_stat __user *statbuf,
                                      int flag);
 asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
index e0670a51205691b10fd0974a9bf42e49620c50ee..ce29b8151198b6c0d40b8f420efe9c2c920d9b4f 100644 (file)
@@ -142,6 +142,7 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
                return -EIO;
 }
 
+#ifdef CONFIG_HAS_DMA
 static inline int dma_get_cache_alignment(void)
 {
 #ifdef ARCH_DMA_MINALIGN
@@ -149,6 +150,7 @@ static inline int dma_get_cache_alignment(void)
 #endif
        return 1;
 }
+#endif
 
 /* flags for the coherent memory api */
 #define        DMA_MEMORY_MAP                  0x01
index 848480bc2bf93846b14e43c0c94493cb2109f889..2308fbb4523a399abce0809860f6f398c8844ed5 100644 (file)
@@ -129,7 +129,7 @@ static inline void random_ether_addr(u8 *addr)
 /**
  * dev_hw_addr_random - Create random MAC and set device flag
  * @dev: pointer to net_device structure
- * @addr: Pointer to a six-byte array containing the Ethernet address
+ * @hwaddr: Pointer to a six-byte array containing the Ethernet address
  *
  * Generate random MAC to be used by a device and set addr_assign_type
  * so the state can be read by sysfs and be used by udev.
index 7a0625e26a3995ca48e91b30e2c874557efc1cb4..9a96b4d83fc126a92adb9c87f7f1e5ae62bc0056 100644 (file)
@@ -1483,8 +1483,8 @@ struct block_device_operations;
 
 /*
  * NOTE:
- * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl
- * can be called without the big kernel lock held in all filesystems.
+ * all file operations except setlease can be called without
+ * the big kernel lock held in all filesystems.
  */
 struct file_operations {
        struct module *owner;
@@ -1495,7 +1495,6 @@ struct file_operations {
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
-       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
@@ -2320,10 +2319,10 @@ void inode_set_bytes(struct inode *inode, loff_t bytes);
 
 extern int vfs_readdir(struct file *, filldir_t, void *);
 
-extern int vfs_stat(char __user *, struct kstat *);
-extern int vfs_lstat(char __user *, struct kstat *);
+extern int vfs_stat(const char __user *, struct kstat *);
+extern int vfs_lstat(const char __user *, struct kstat *);
 extern int vfs_fstat(unsigned int, struct kstat *);
-extern int vfs_fstatat(int , char __user *, struct kstat *, int);
+extern int vfs_fstatat(int , const char __user *, struct kstat *, int);
 
 extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
                    unsigned long arg);
index 413742c92d14efce0e98743a101a67fb3e8c2f97..791d5109f34c12207de65f06cca05fa4b35b44b8 100644 (file)
@@ -122,7 +122,7 @@ static inline int netpoll_tx_running(struct net_device *dev)
 }
 
 #else
-static inline int netpoll_rx(struct sk_buff *skb)
+static inline bool netpoll_rx(struct sk_buff *skb)
 {
        return 0;
 }
index 1b67bd333b5e4097a9d6debb6498219006c01957..6e5d19788634f751ab18e980c2cee847bb7d3560 100644 (file)
@@ -394,7 +394,7 @@ asmlinkage long sys_umount(char __user *name, int flags);
 asmlinkage long sys_oldumount(char __user *name);
 asmlinkage long sys_truncate(const char __user *path, long length);
 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-asmlinkage long sys_stat(char __user *filename,
+asmlinkage long sys_stat(const char __user *filename,
                        struct __old_kernel_stat __user *statbuf);
 asmlinkage long sys_statfs(const char __user * path,
                                struct statfs __user *buf);
@@ -403,21 +403,21 @@ asmlinkage long sys_statfs64(const char __user *path, size_t sz,
 asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf);
 asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz,
                                struct statfs64 __user *buf);
-asmlinkage long sys_lstat(char __user *filename,
+asmlinkage long sys_lstat(const char __user *filename,
                        struct __old_kernel_stat __user *statbuf);
 asmlinkage long sys_fstat(unsigned int fd,
                        struct __old_kernel_stat __user *statbuf);
-asmlinkage long sys_newstat(char __user *filename,
+asmlinkage long sys_newstat(const char __user *filename,
                                struct stat __user *statbuf);
-asmlinkage long sys_newlstat(char __user *filename,
+asmlinkage long sys_newlstat(const char __user *filename,
                                struct stat __user *statbuf);
 asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);
 asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
 #if BITS_PER_LONG == 32
-asmlinkage long sys_stat64(char __user *filename,
+asmlinkage long sys_stat64(const char __user *filename,
                                struct stat64 __user *statbuf);
 asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
-asmlinkage long sys_lstat64(char __user *filename,
+asmlinkage long sys_lstat64(const char __user *filename,
                                struct stat64 __user *statbuf);
 asmlinkage long sys_truncate64(const char __user *path, loff_t length);
 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
@@ -760,7 +760,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
                           int newdfd, const char __user *newname, int flags);
 asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
                             int newdfd, const char __user * newname);
-asmlinkage long sys_futimesat(int dfd, char __user *filename,
+asmlinkage long sys_futimesat(int dfd, const char __user *filename,
                              struct timeval __user *utimes);
 asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
 asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
@@ -769,13 +769,13 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
                             gid_t group, int flag);
 asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
                           int mode);
-asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+asmlinkage long sys_newfstatat(int dfd, const char __user *filename,
                               struct stat __user *statbuf, int flag);
-asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+asmlinkage long sys_fstatat64(int dfd, const char __user *filename,
                               struct stat64 __user *statbuf, int flag);
 asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
                               int bufsiz);
-asmlinkage long sys_utimensat(int dfd, char __user *filename,
+asmlinkage long sys_utimensat(int dfd, const char __user *filename,
                                struct timespec __user *utimes, int flags);
 asmlinkage long sys_unshare(unsigned long unshare_flags);
 
index 12612701b1ae464c4e0591114a4f14a7d284e88a..9f15ac7ab92a7b224a9e1208f13c715459443246 100644 (file)
@@ -150,7 +150,7 @@ extern void do_gettimeofday(struct timeval *tv);
 extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
 #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
-extern long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags);
+extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value,
                        struct itimerval *ovalue);
index 636724b203eef0f2c6fa519fe626df2a707029d3..6c241444f902800baf1c4cd16aa89d767d751065 100644 (file)
@@ -33,9 +33,9 @@
 #define L2CAP_DEFAULT_FLUSH_TO         0xffff
 #define L2CAP_DEFAULT_TX_WINDOW                63
 #define L2CAP_DEFAULT_MAX_TX           3
-#define L2CAP_DEFAULT_RETRANS_TO       1000    /* 1 second */
+#define L2CAP_DEFAULT_RETRANS_TO       2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO       12000   /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE     672
+#define L2CAP_DEFAULT_MAX_PDU_SIZE     1009    /* Sized for 3-DH5 packet */
 #define L2CAP_DEFAULT_ACK_TO           200
 #define L2CAP_LOCAL_BUSY_TRIES         12
 
index a441c9cdd62540cd7100189c5fa7aea2f6b0b22b..ac53bfbdfe16b57038cf6c0b7f88cc88f5221594 100644 (file)
@@ -195,7 +195,8 @@ struct sock_common {
   *    @sk_priority: %SO_PRIORITY setting
   *    @sk_type: socket type (%SOCK_STREAM, etc)
   *    @sk_protocol: which protocol this socket belongs in this network family
-  *    @sk_peercred: %SO_PEERCRED setting
+  *    @sk_peer_pid: &struct pid for this socket's peer
+  *    @sk_peer_cred: %SO_PEERCRED setting
   *    @sk_rcvlowat: %SO_RCVLOWAT setting
   *    @sk_rcvtimeo: %SO_RCVTIMEO setting
   *    @sk_sndtimeo: %SO_SNDTIMEO setting
@@ -211,6 +212,7 @@ struct sock_common {
   *    @sk_send_head: front of stuff to transmit
   *    @sk_security: used by security modules
   *    @sk_mark: generic packet mark
+  *    @sk_classid: this socket's cgroup classid
   *    @sk_write_pending: a write to stream socket waits to start
   *    @sk_state_change: callback to indicate change in the state of the sock
   *    @sk_data_ready: callback to indicate there is data to be processed
index e960d824263f1d04aa17c5e256ec56a4cdfa5fd1..49010d822f725b47726742fa7e1b45aad076ef90 100644 (file)
@@ -710,9 +710,10 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
        /* Accumulate raw time */
        raw_nsecs = timekeeper.raw_interval << shift;
        raw_nsecs += raw_time.tv_nsec;
-       while (raw_nsecs >= NSEC_PER_SEC) {
-               raw_nsecs -= NSEC_PER_SEC;
-               raw_time.tv_sec++;
+       if (raw_nsecs >= NSEC_PER_SEC) {
+               u64 raw_secs = raw_nsecs;
+               raw_nsecs = do_div(raw_secs, NSEC_PER_SEC);
+               raw_time.tv_sec += raw_secs;
        }
        raw_time.tv_nsec = raw_nsecs;
 
index 9606ceb3c16536a0ba45975cd592bd353830085f..9b3b73f4ae9c77350abd052abbdc889634258801 100644 (file)
@@ -2792,8 +2792,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
        spinlock_t *ptl;
        pte_t entry;
 
-       if (check_stack_guard_page(vma, address) < 0)
+       if (check_stack_guard_page(vma, address) < 0) {
+               pte_unmap(page_table);
                return VM_FAULT_SIGBUS;
+       }
 
        if (!(flags & FAULT_FLAG_WRITE)) {
                entry = pte_mkspecial(pfn_pte(my_zero_pfn(address),
index b76f3ee0abe015a85f36ff4b2599cff21d3c3efd..efa9a380335eed137c30d5c762c5a5cdae469b9c 100644 (file)
 #include <asm/mmu_context.h>
 #include "internal.h"
 
-static inline __attribute__((format(printf, 1, 2)))
-void no_printk(const char *fmt, ...)
-{
-}
-
 #if 0
 #define kenter(FMT, ...) \
        printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
index 3e3cd9d4e52ce6147ed5b506a8d4cb3f6248d85e..fadf26b4ed7c432eba09800b4532683fc44cc02d 100644 (file)
@@ -2705,8 +2705,9 @@ done:
                case L2CAP_MODE_ERTM:
                        pi->remote_tx_win = rfc.txwin_size;
                        pi->remote_max_tx = rfc.max_transmit;
-                       if (rfc.max_pdu_size > pi->conn->mtu - 10)
-                               rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+
+                       if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+                               rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
                        pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
@@ -2723,8 +2724,8 @@ done:
                        break;
 
                case L2CAP_MODE_STREAMING:
-                       if (rfc.max_pdu_size > pi->conn->mtu - 10)
-                               rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
+                       if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+                               rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
                        pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
@@ -2806,7 +2807,6 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
        if (*result == L2CAP_CONF_SUCCESS) {
                switch (rfc.mode) {
                case L2CAP_MODE_ERTM:
-                       pi->remote_tx_win   = rfc.txwin_size;
                        pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
                        pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
                        pi->mps    = le16_to_cpu(rfc.max_pdu_size);
@@ -2862,7 +2862,6 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
 done:
        switch (rfc.mode) {
        case L2CAP_MODE_ERTM:
-               pi->remote_tx_win   = rfc.txwin_size;
                pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
                pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
                pi->mps    = le16_to_cpu(rfc.max_pdu_size);
index 01f238ff23466912ad1c243b6ca88b8a0c998f8b..c49a6695793ac8361b072077aefa4e2b863e8f5c 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/hardirq.h>
 #include <net/caif/cfpkt.h>
 
-#define PKT_PREFIX  16
+#define PKT_PREFIX  48
 #define PKT_POSTFIX 2
 #define PKT_LEN_WHEN_EXTENDING 128
 #define PKT_ERROR(pkt, errmsg) do {       \
index 9c65e9deb9c3ff6d6f958f4b52ee7e85d6299935..08ffe9e4be20aa49ab2bba82c36c5e988a4880fd 100644 (file)
 #include <net/sock.h>
 #include <net/net_namespace.h>
 
+/*
+ * To send multiple CAN frame content within TX_SETUP or to filter
+ * CAN messages with multiplex index within RX_SETUP, the number of
+ * different filters is limited to 256 due to the one byte index value.
+ */
+#define MAX_NFRAMES 256
+
 /* use of last_frames[index].can_dlc */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -89,16 +96,16 @@ struct bcm_op {
        struct list_head list;
        int ifindex;
        canid_t can_id;
-       int flags;
+       u32 flags;
        unsigned long frames_abs, frames_filtered;
        struct timeval ival1, ival2;
        struct hrtimer timer, thrtimer;
        struct tasklet_struct tsklet, thrtsklet;
        ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
        int rx_ifindex;
-       int count;
-       int nframes;
-       int currframe;
+       u32 count;
+       u32 nframes;
+       u32 currframe;
        struct can_frame *frames;
        struct can_frame *last_frames;
        struct can_frame sframe;
@@ -175,7 +182,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 
                seq_printf(m, "rx_op: %03X %-5s ",
                                op->can_id, bcm_proc_getifname(ifname, op->ifindex));
-               seq_printf(m, "[%d]%c ", op->nframes,
+               seq_printf(m, "[%u]%c ", op->nframes,
                                (op->flags & RX_CHECK_DLC)?'d':' ');
                if (op->kt_ival1.tv64)
                        seq_printf(m, "timeo=%lld ",
@@ -198,7 +205,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 
        list_for_each_entry(op, &bo->tx_ops, list) {
 
-               seq_printf(m, "tx_op: %03X %s [%d] ",
+               seq_printf(m, "tx_op: %03X %s [%u] ",
                                op->can_id,
                                bcm_proc_getifname(ifname, op->ifindex),
                                op->nframes);
@@ -283,7 +290,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
        struct can_frame *firstframe;
        struct sockaddr_can *addr;
        struct sock *sk = op->sk;
-       int datalen = head->nframes * CFSIZ;
+       unsigned int datalen = head->nframes * CFSIZ;
        int err;
 
        skb = alloc_skb(sizeof(*head) + datalen, gfp_any());
@@ -468,7 +475,7 @@ rx_changed_settime:
  * bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly
  *                       received data stored in op->last_frames[]
  */
-static void bcm_rx_cmp_to_index(struct bcm_op *op, int index,
+static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index,
                                const struct can_frame *rxdata)
 {
        /*
@@ -554,7 +561,8 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
 /*
  * bcm_rx_do_flush - helper for bcm_rx_thr_flush
  */
-static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index)
+static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
+                                 unsigned int index)
 {
        if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) {
                if (update)
@@ -575,7 +583,7 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update)
        int updated = 0;
 
        if (op->nframes > 1) {
-               int i;
+               unsigned int i;
 
                /* for MUX filter we start at index 1 */
                for (i = 1; i < op->nframes; i++)
@@ -624,7 +632,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
 {
        struct bcm_op *op = (struct bcm_op *)data;
        const struct can_frame *rxframe = (struct can_frame *)skb->data;
-       int i;
+       unsigned int i;
 
        /* disable timeout */
        hrtimer_cancel(&op->timer);
@@ -822,14 +830,15 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 {
        struct bcm_sock *bo = bcm_sk(sk);
        struct bcm_op *op;
-       int i, err;
+       unsigned int i;
+       int err;
 
        /* we need a real device to send frames */
        if (!ifindex)
                return -ENODEV;
 
-       /* we need at least one can_frame */
-       if (msg_head->nframes < 1)
+       /* check nframes boundaries - we need at least one can_frame */
+       if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
                return -EINVAL;
 
        /* check the given can_id */
@@ -993,6 +1002,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                msg_head->nframes = 0;
        }
 
+       /* the first element contains the mux-mask => MAX_NFRAMES + 1  */
+       if (msg_head->nframes > MAX_NFRAMES + 1)
+               return -EINVAL;
+
        if ((msg_head->flags & RX_RTR_FRAME) &&
            ((msg_head->nframes != 1) ||
             (!(msg_head->can_id & CAN_RTR_FLAG))))
index 400a04d5c9a1335216f6bebca3b2892ec99a3d6b..739435a6af3983fa2776a4b402a51d9d7aefeec8 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/keyctl.h>
 #include <linux/err.h>
+#include <linux/seq_file.h>
 #include <keys/dns_resolver-type.h>
 #include <keys/user-type.h>
 #include "internal.h"
@@ -43,6 +44,8 @@ MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
 
 const struct cred *dns_resolver_cache;
 
+#define        DNS_ERRORNO_OPTION      "dnserror"
+
 /*
  * Instantiate a user defined key for dns_resolver.
  *
@@ -59,9 +62,10 @@ static int
 dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
 {
        struct user_key_payload *upayload;
+       unsigned long derrno;
        int ret;
        size_t result_len = 0;
-       const char *data = _data, *opt;
+       const char *data = _data, *end, *opt;
 
        kenter("%%%d,%s,'%s',%zu",
               key->serial, key->description, data, datalen);
@@ -71,13 +75,77 @@ dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
        datalen--;
 
        /* deal with any options embedded in the data */
+       end = data + datalen;
        opt = memchr(data, '#', datalen);
        if (!opt) {
-               kdebug("no options currently supported");
-               return -EINVAL;
+               /* no options: the entire data is the result */
+               kdebug("no options");
+               result_len = datalen;
+       } else {
+               const char *next_opt;
+
+               result_len = opt - data;
+               opt++;
+               kdebug("options: '%s'", opt);
+               do {
+                       const char *eq;
+                       int opt_len, opt_nlen, opt_vlen, tmp;
+
+                       next_opt = memchr(opt, '#', end - opt) ?: end;
+                       opt_len = next_opt - opt;
+                       if (!opt_len) {
+                               printk(KERN_WARNING
+                                      "Empty option to dns_resolver key %d\n",
+                                      key->serial);
+                               return -EINVAL;
+                       }
+
+                       eq = memchr(opt, '=', opt_len) ?: end;
+                       opt_nlen = eq - opt;
+                       eq++;
+                       opt_vlen = next_opt - eq; /* will be -1 if no value */
+
+                       tmp = opt_vlen >= 0 ? opt_vlen : 0;
+                       kdebug("option '%*.*s' val '%*.*s'",
+                              opt_nlen, opt_nlen, opt, tmp, tmp, eq);
+
+                       /* see if it's an error number representing a DNS error
+                        * that's to be recorded as the result in this key */
+                       if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 &&
+                           memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) {
+                               kdebug("dns error number option");
+                               if (opt_vlen <= 0)
+                                       goto bad_option_value;
+
+                               ret = strict_strtoul(eq, 10, &derrno);
+                               if (ret < 0)
+                                       goto bad_option_value;
+
+                               if (derrno < 1 || derrno > 511)
+                                       goto bad_option_value;
+
+                               kdebug("dns error no. = %lu", derrno);
+                               key->type_data.x[0] = -derrno;
+                               continue;
+                       }
+
+               bad_option_value:
+                       printk(KERN_WARNING
+                              "Option '%*.*s' to dns_resolver key %d:"
+                              " bad/missing value\n",
+                              opt_nlen, opt_nlen, opt, key->serial);
+                       return -EINVAL;
+               } while (opt = next_opt + 1, opt < end);
+       }
+
+       /* don't cache the result if we're caching an error saying there's no
+        * result */
+       if (key->type_data.x[0]) {
+               kleave(" = 0 [h_error %ld]", key->type_data.x[0]);
+               return 0;
        }
 
-       result_len = datalen;
+       kdebug("store result");
        ret = key_payload_reserve(key, result_len);
        if (ret < 0)
                return -EINVAL;
@@ -135,13 +203,27 @@ no_match:
        return ret;
 }
 
+/*
+ * Describe a DNS key
+ */
+static void dns_resolver_describe(const struct key *key, struct seq_file *m)
+{
+       int err = key->type_data.x[0];
+
+       seq_puts(m, key->description);
+       if (err)
+               seq_printf(m, ": %d", err);
+       else
+               seq_printf(m, ": %u", key->datalen);
+}
+
 struct key_type key_type_dns_resolver = {
        .name           = "dns_resolver",
        .instantiate    = dns_resolver_instantiate,
        .match          = dns_resolver_match,
        .revoke         = user_revoke,
        .destroy        = user_destroy,
-       .describe       = user_describe,
+       .describe       = dns_resolver_describe,
        .read           = user_read,
 };
 
index 03d5255f5cf2a08cd4a1efe8d4a57638d5c15f65..c32be292c7e382c4a2c600e9e3c559906ff9784b 100644 (file)
@@ -136,6 +136,11 @@ int dns_query(const char *type, const char *name, size_t namelen,
        if (ret < 0)
                goto put;
 
+       /* If the DNS server gave an error, return that to the caller */
+       ret = rkey->type_data.x[0];
+       if (ret)
+               goto put;
+
        upayload = rcu_dereference_protected(rkey->payload.data,
                                             lockdep_is_held(&rkey->sem));
        len = upayload->datalen;
index 11201784d29a32d6fdddd972a8348d3202de0ec9..87bb5f4de0e84601817a0f63733a725ebb478b03 100644 (file)
@@ -1,7 +1,7 @@
 menuconfig NET_DSA
        bool "Distributed Switch Architecture support"
        default n
-       depends on EXPERIMENTAL && NET_ETHERNET && !S390
+       depends on EXPERIMENTAL && NETDEVICES && !S390
        select PHYLIB
        ---help---
          This allows you to use hardware switch chips that use
index b9e8c3b7d406aacd9cc2319ddbffe0440cc6c311..408eea7086aace341d1ed9812d956db35cfdfb86 100644 (file)
@@ -150,22 +150,34 @@ int register_qdisc(struct Qdisc_ops *qops)
        if (qops->enqueue == NULL)
                qops->enqueue = noop_qdisc_ops.enqueue;
        if (qops->peek == NULL) {
-               if (qops->dequeue == NULL) {
+               if (qops->dequeue == NULL)
                        qops->peek = noop_qdisc_ops.peek;
-               } else {
-                       rc = -EINVAL;
-                       goto out;
-               }
+               else
+                       goto out_einval;
        }
        if (qops->dequeue == NULL)
                qops->dequeue = noop_qdisc_ops.dequeue;
 
+       if (qops->cl_ops) {
+               const struct Qdisc_class_ops *cops = qops->cl_ops;
+
+               if (!(cops->get && cops->put && cops->walk && cops->leaf))
+                       goto out_einval;
+
+               if (cops->tcf_chain && !(cops->bind_tcf && cops->unbind_tcf))
+                       goto out_einval;
+       }
+
        qops->next = NULL;
        *qp = qops;
        rc = 0;
 out:
        write_unlock(&qdisc_mod_lock);
        return rc;
+
+out_einval:
+       rc = -EINVAL;
+       goto out;
 }
 EXPORT_SYMBOL(register_qdisc);
 
index e114f23d5eaeb189428fbf4d307669da80e4f255..3406627895298324fdd9d27186ad8c9c8d9a9964 100644 (file)
@@ -418,7 +418,7 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
 
        ret = qdisc_enqueue(skb, flow->q);
-       if (ret != 0) {
+       if (ret != NET_XMIT_SUCCESS) {
 drop: __maybe_unused
                if (net_xmit_drop_count(ret)) {
                        sch->qstats.drops++;
@@ -442,7 +442,7 @@ drop: __maybe_unused
         */
        if (flow == &p->link) {
                sch->q.qlen++;
-               return 0;
+               return NET_XMIT_SUCCESS;
        }
        tasklet_schedule(&p->task);
        return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
index 534f33231c17d83593f124fa62d110d630c2fc0d..201cbac2b32ce0ccd8375b066005b6ba69759ddd 100644 (file)
@@ -334,7 +334,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (++sch->q.qlen <= q->limit) {
                sch->bstats.bytes += qdisc_pkt_len(skb);
                sch->bstats.packets++;
-               return 0;
+               return NET_XMIT_SUCCESS;
        }
 
        sfq_drop(sch);
@@ -508,6 +508,11 @@ nla_put_failure:
        return -1;
 }
 
+static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg)
+{
+       return NULL;
+}
+
 static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
 {
        return 0;
@@ -519,6 +524,10 @@ static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
        return 0;
 }
 
+static void sfq_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
 static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl)
 {
        struct sfq_sched_data *q = qdisc_priv(sch);
@@ -571,9 +580,12 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 }
 
 static const struct Qdisc_class_ops sfq_class_ops = {
+       .leaf           =       sfq_leaf,
        .get            =       sfq_get,
+       .put            =       sfq_put,
        .tcf_chain      =       sfq_find_tcf,
        .bind_tcf       =       sfq_bind,
+       .unbind_tcf     =       sfq_put,
        .dump           =       sfq_dump_class,
        .dump_stats     =       sfq_dump_class_stats,
        .walk           =       sfq_walk,
index 0991c640cd3e8f3e5ae836c44b16b9e27f743c7e..641a30d646356867b808ac86d7bac59901fe2729 100644 (file)
@@ -127,7 +127,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                return qdisc_reshape_fail(skb, sch);
 
        ret = qdisc_enqueue(skb, q->qdisc);
-       if (ret != 0) {
+       if (ret != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret))
                        sch->qstats.drops++;
                return ret;
@@ -136,7 +136,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
        sch->q.qlen++;
        sch->bstats.bytes += qdisc_pkt_len(skb);
        sch->bstats.packets++;
-       return 0;
+       return NET_XMIT_SUCCESS;
 }
 
 static unsigned int tbf_drop(struct Qdisc* sch)
index 807643bdcbac30817edecfb4185dd45826b750eb..feaabc103ce6a061e350ddb07e1a2faf5d1ee4bd 100644 (file)
@@ -85,7 +85,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                __skb_queue_tail(&q->q, skb);
                sch->bstats.bytes += qdisc_pkt_len(skb);
                sch->bstats.packets++;
-               return 0;
+               return NET_XMIT_SUCCESS;
        }
 
        kfree_skb(skb);
index e74a1a2119d34a334702bc16106c43fefa2ffdbd..d1a3fb99fdf2caaa83e5b476dd3166c18f436161 100644 (file)
@@ -843,13 +843,19 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
                return -EINVAL;
        if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
                /* Verify that we are associated with the destination AP */
+               wdev_lock(wdev);
+
                if (!wdev->current_bss ||
                    memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
                           ETH_ALEN) != 0 ||
                    (wdev->iftype == NL80211_IFTYPE_STATION &&
                     memcmp(wdev->current_bss->pub.bssid, mgmt->da,
-                           ETH_ALEN) != 0))
+                           ETH_ALEN) != 0)) {
+                       wdev_unlock(wdev);
                        return -ENOTCONN;
+               }
+
+               wdev_unlock(wdev);
        }
 
        if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
index 274f2716b03e9d4b0a5865a86a09b11799359523..5b7c86ea43a1e3f27484ccfc83f8d2992ad548a4 100644 (file)
@@ -108,7 +108,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)
                check_stdin();
        case oldaskconfig:
                fflush(stdout);
-               fgets(line, 128, stdin);
+               xfgets(line, 128, stdin);
                return 1;
        default:
                break;
@@ -306,7 +306,7 @@ static int conf_choice(struct menu *menu)
                        check_stdin();
                case oldaskconfig:
                        fflush(stdout);
-                       fgets(line, 128, stdin);
+                       xfgets(line, 128, stdin);
                        strip(line);
                        if (line[0] == '?') {
                                print_help(menu);
@@ -644,3 +644,14 @@ int main(int ac, char **av)
        }
        return 0;
 }
+/*
+ * Helper function to facilitate fgets() by Jean Sacren.
+ */
+void xfgets(str, size, in)
+       char *str;
+       int size;
+       FILE *in;
+{
+       if (fgets(str, size, in) == NULL)
+               fprintf(stderr, "\nError in reading or end of file.\n");
+}
index f81f263b64f27ee166d56020b6ecce7043523811..c39327e60ea499919937fae08a8d5bc5dc9c4fd9 100644 (file)
@@ -412,7 +412,7 @@ static void conf_write_string(bool headerfile, const char *name,
        while (1) {
                l = strcspn(str, "\"\\");
                if (l) {
-                       fwrite(str, l, 1, out);
+                       xfwrite(str, l, 1, out);
                        str += l;
                }
                if (!*str)
@@ -497,7 +497,7 @@ int conf_write_defconfig(const char *filename)
                        /*
                         * If symbol is a choice value and equals to the
                         * default for a choice - skip.
-                        * But only if value equal to "y".
+                        * But only if value is bool and equal to "y" .
                         */
                        if (sym_is_choice_value(sym)) {
                                struct symbol *cs;
@@ -506,9 +506,8 @@ int conf_write_defconfig(const char *filename)
                                cs = prop_get_symbol(sym_get_choice_prop(sym));
                                ds = sym_choice_default(cs);
                                if (sym == ds) {
-                                       if ((sym->type == S_BOOLEAN ||
-                                       sym->type == S_TRISTATE) &&
-                                       sym_get_tristate_value(sym) == yes)
+                                       if ((sym->type == S_BOOLEAN) &&
+                                           sym_get_tristate_value(sym) == yes)
                                                goto next_menu;
                                }
                        }
@@ -919,13 +918,73 @@ void conf_set_changed_callback(void (*fn)(void))
        conf_changed_callback = fn;
 }
 
+static void randomize_choice_values(struct symbol *csym)
+{
+       struct property *prop;
+       struct symbol *sym;
+       struct expr *e;
+       int cnt, def;
 
-void conf_set_all_new_symbols(enum conf_def_mode mode)
+       /*
+        * If choice is mod then we may have more items slected
+        * and if no then no-one.
+        * In both cases stop.
+        */
+       if (csym->curr.tri != yes)
+               return;
+
+       prop = sym_get_choice_prop(csym);
+
+       /* count entries in choice block */
+       cnt = 0;
+       expr_list_for_each_sym(prop->expr, e, sym)
+               cnt++;
+
+       /*
+        * find a random value and set it to yes,
+        * set the rest to no so we have only one set
+        */
+       def = (rand() % cnt);
+
+       cnt = 0;
+       expr_list_for_each_sym(prop->expr, e, sym) {
+               if (def == cnt++) {
+                       sym->def[S_DEF_USER].tri = yes;
+                       csym->def[S_DEF_USER].val = sym;
+               }
+               else {
+                       sym->def[S_DEF_USER].tri = no;
+               }
+       }
+       csym->flags |= SYMBOL_DEF_USER;
+       /* clear VALID to get value calculated */
+       csym->flags &= ~(SYMBOL_VALID);
+}
+
+static void set_all_choice_values(struct symbol *csym)
 {
-       struct symbol *sym, *csym;
        struct property *prop;
+       struct symbol *sym;
        struct expr *e;
-       int i, cnt, def;
+
+       prop = sym_get_choice_prop(csym);
+
+       /*
+        * Set all non-assinged choice values to no
+        */
+       expr_list_for_each_sym(prop->expr, e, sym) {
+               if (!sym_has_value(sym))
+                       sym->def[S_DEF_USER].tri = no;
+       }
+       csym->flags |= SYMBOL_DEF_USER;
+       /* clear VALID to get value calculated */
+       csym->flags &= ~(SYMBOL_VALID);
+}
+
+void conf_set_all_new_symbols(enum conf_def_mode mode)
+{
+       struct symbol *sym, *csym;
+       int i, cnt;
 
        for_all_symbols(i, sym) {
                if (sym_has_value(sym))
@@ -961,8 +1020,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
 
        sym_clear_all_valid();
 
-       if (mode != def_random)
-               return;
        /*
         * We have different type of choice blocks.
         * If curr.tri equal to mod then we can select several
@@ -977,35 +1034,9 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                        continue;
 
                sym_calc_value(csym);
-
-               if (csym->curr.tri != yes)
-                       continue;
-
-               prop = sym_get_choice_prop(csym);
-
-               /* count entries in choice block */
-               cnt = 0;
-               expr_list_for_each_sym(prop->expr, e, sym)
-                       cnt++;
-
-               /*
-                * find a random value and set it to yes,
-                * set the rest to no so we have only one set
-                */
-               def = (rand() % cnt);
-
-               cnt = 0;
-               expr_list_for_each_sym(prop->expr, e, sym) {
-                       if (def == cnt++) {
-                               sym->def[S_DEF_USER].tri = yes;
-                               csym->def[S_DEF_USER].val = sym;
-                       }
-                       else {
-                               sym->def[S_DEF_USER].tri = no;
-                       }
-               }
-               csym->flags |= SYMBOL_DEF_USER;
-               /* clear VALID to get value calculated */
-               csym->flags &= ~(SYMBOL_VALID);
+               if (mode == def_random)
+                       randomize_choice_values(csym);
+               else
+                       set_all_choice_values(csym);
        }
 }
index 8f18e37892cb42152ddda716edb6ae4f5592e7ac..330e7c0048a85ea1939562e724eaa7f2326d56ab 100644 (file)
@@ -1087,7 +1087,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
 
 static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
 {
-       fwrite(str, strlen(str), 1, data);
+       xfwrite(str, strlen(str), 1, data);
 }
 
 void expr_fprint(struct expr *e, FILE *out)
index 76db065ed72c069aa4371d875bdcfe71c96a9316..bdf71bd314127755cdf3f5d5d3ac02ecbeeb1f71 100644 (file)
@@ -72,6 +72,9 @@ void zconf_nextfile(const char *name);
 int zconf_lineno(void);
 char *zconf_curname(void);
 
+/* conf.c */
+void xfgets(char *str, int size, FILE *in);
+
 /* confdata.c */
 const char *conf_get_configname(void);
 const char *conf_get_autoconfig_name(void);
@@ -80,6 +83,13 @@ void sym_set_change_count(int count);
 void sym_add_change_count(int count);
 void conf_set_all_new_symbols(enum conf_def_mode mode);
 
+/* confdata.c and expr.c */
+static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
+{
+       if (fwrite(str, len, count, out) < count)
+               fprintf(stderr, "\nError in writing or end of file.\n");
+}
+
 /* kconfig_load.c */
 void kconfig_load(void);
 
index 762caf80ce37d3822d43bf0a151ffcf8b8a17d21..2ba71bcd38e65381aa347e093a2dc7b338d03dc0 100644 (file)
@@ -676,6 +676,8 @@ static void *item_data(void)
        struct mitem *mcur;
 
        cur = current_item(curses_menu);
+       if (!cur)
+               return NULL;
        mcur = (struct mitem *) item_userptr(cur);
        return mcur->usrptr;
 
index 64a9cb5556cd0f90dab503c6b8cd96e2fa7bff1d..e90a91cc5185709d31a9a128b4790b676a35599e 100755 (executable)
@@ -86,7 +86,7 @@ scm_version()
 
        # Check for mercurial and a mercurial repo.
        if hgid=`hg id 2>/dev/null`; then
-               tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+               tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
 
                # Do we have an untagged version?
                if [ -z "$tag" -o "$tag" = tip ]; then
index 26f626d45a9e2bb0a7e5157f48ddfe7c9a0851fe..41abb90df50d1fdf97a062e5be387613c7131ee6 100644 (file)
@@ -157,9 +157,8 @@ all::
 #
 # Define NO_DWARF if you do not want debug-info analysis feature at all.
 
-$(shell sh -c 'mkdir -p $(OUTPUT)scripts/python/Perf-Trace-Util/' 2> /dev/null)
-$(shell sh -c 'mkdir -p $(OUTPUT)scripts/perl/Perf-Trace-Util/' 2> /dev/null)
-$(shell sh -c 'mkdir -p $(OUTPUT)util/scripting-engines/' 2> /dev/null)
+$(shell sh -c 'mkdir -p $(OUTPUT)scripts/{perl,python}/Perf-Trace-Util/' 2> /dev/null)
+$(shell sh -c 'mkdir -p $(OUTPUT)util/{ui/browsers,scripting-engines}/' 2> /dev/null)
 $(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null)
 
 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
@@ -568,7 +567,20 @@ else
                # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
                BASIC_CFLAGS += -I/usr/include/slang
                EXTLIBS += -lnewt -lslang
-               LIB_OBJS += $(OUTPUT)util/newt.o
+               LIB_OBJS += $(OUTPUT)util/ui/setup.o
+               LIB_OBJS += $(OUTPUT)util/ui/browser.o
+               LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
+               LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
+               LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
+               LIB_OBJS += $(OUTPUT)util/ui/helpline.o
+               LIB_OBJS += $(OUTPUT)util/ui/progress.o
+               LIB_OBJS += $(OUTPUT)util/ui/util.o
+               LIB_H += util/ui/browser.h
+               LIB_H += util/ui/browsers/map.h
+               LIB_H += util/ui/helpline.h
+               LIB_H += util/ui/libslang.h
+               LIB_H += util/ui/progress.h
+               LIB_H += util/ui/util.h
        endif
 endif
 
@@ -966,7 +978,16 @@ $(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
-$(OUTPUT)util/newt.o: util/newt.c $(OUTPUT)PERF-CFLAGS
+$(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
 
 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
index fd20670ce986bae016759aa61bd01c272bd7f47f..1478dc64bf157fc0f226cba51eef80ec8646c15f 100644 (file)
@@ -285,7 +285,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he)
        LIST_HEAD(head);
        struct objdump_line *pos, *n;
 
-       if (hist_entry__annotate(he, &head) < 0)
+       if (hist_entry__annotate(he, &head, 0) < 0)
                return -1;
 
        if (full_paths)
index 2f4b92925b2619a85d615ed109851c78619f4465..55fc1f46892a6a920411db7dc91226bcbe6a7f82 100644 (file)
@@ -348,7 +348,18 @@ static int __cmd_report(void)
                hists__tty_browse_tree(&session->hists_tree, help);
 
 out_delete:
-       perf_session__delete(session);
+       /*
+        * Speed up the exit process, for large files this can
+        * take quite a while.
+        *
+        * XXX Enable this when using valgrind or if we ever
+        * librarize this command.
+        *
+        * Also experiment with obstacks to see how much speed
+        * up we'll get here.
+        *
+        * perf_session__delete(session);
+        */
        return ret;
 }
 
@@ -478,8 +489,24 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
         * so don't allocate extra space that won't be used in the stdio
         * implementation.
         */
-       if (use_browser > 0)
+       if (use_browser > 0) {
                symbol_conf.priv_size = sizeof(struct sym_priv);
+               /*
+                * For searching by name on the "Browse map details".
+                * providing it only in verbose mode not to bloat too
+                * much struct symbol.
+                */
+               if (verbose) {
+                       /*
+                        * XXX: Need to provide a less kludgy way to ask for
+                        * more space per symbol, the u32 is for the index on
+                        * the ui browser.
+                        * See symbol__browser_index.
+                        */
+                       symbol_conf.priv_size += sizeof(u32);
+                       symbol_conf.sort_by_name = true;
+               }
+       }
 
        if (symbol__init() < 0)
                return -1;
index 5161619d4714d3838579d82d91f543b117a4535a..9bcc38f0b706f91ca3701e440c15e3e9c8aa7bd3 100644 (file)
@@ -455,8 +455,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
                if (p->current->state != TYPE_NONE)
                        pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp);
 
-                       p->current->state_since = timestamp;
-                       p->current->state = TYPE_RUNNING;
+               p->current->state_since = timestamp;
+               p->current->state = TYPE_RUNNING;
        }
 
        if (prev_p->current) {
index 294da725a57d12867788baa9c5ea98c410486cdf..40a6a2992d15b286a883ebbbb0f5dd4c10d0e6c5 100644 (file)
@@ -1,13 +1,16 @@
 #include "builtin.h"
 
-#include "util/util.h"
+#include "perf.h"
 #include "util/cache.h"
+#include "util/debug.h"
+#include "util/exec_cmd.h"
+#include "util/header.h"
+#include "util/parse-options.h"
+#include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
-#include "util/header.h"
-#include "util/exec_cmd.h"
 #include "util/trace-event.h"
-#include "util/session.h"
+#include "util/util.h"
 
 static char const              *script_name;
 static char const              *generate_script_lang;
@@ -59,14 +62,6 @@ static int cleanup_scripting(void)
        return scripting_ops->stop_script();
 }
 
-#include "util/parse-options.h"
-
-#include "perf.h"
-#include "util/debug.h"
-
-#include "util/trace-event.h"
-#include "util/exec_cmd.h"
-
 static char const              *input_name = "perf.data";
 
 static int process_sample_event(event_t *event, struct perf_session *session)
index 318dab15d17732a709ab7b72b8db03fb6e08b24f..f9c7e3ad1aa715db6d562a45029a747800c20d6d 100644 (file)
@@ -23,7 +23,7 @@ int eprintf(int level, const char *fmt, ...)
        if (verbose >= level) {
                va_start(args, fmt);
                if (use_browser > 0)
-                       ret = browser__show_help(fmt, args);
+                       ret = ui_helpline__show_help(fmt, args);
                else
                        ret = vfprintf(stderr, fmt, args);
                va_end(args);
index 047ac3324ebe0948aefddac341f6994f1f896cce..7a17ee061bcbd4c80ed42084e12bc61b834fa8b3 100644 (file)
@@ -14,7 +14,7 @@ void trace_event(event_t *event);
 struct ui_progress;
 
 #ifdef NO_NEWT_SUPPORT
-static inline int browser__show_help(const char *format __used, va_list ap __used)
+static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
 {
        return 0;
 }
@@ -30,10 +30,9 @@ static inline void ui_progress__update(struct ui_progress *self __used,
 
 static inline void ui_progress__delete(struct ui_progress *self __used) {}
 #else
-int browser__show_help(const char *format, va_list ap);
-struct ui_progress *ui_progress__new(const char *title, u64 total);
-void ui_progress__update(struct ui_progress *self, u64 curr);
-void ui_progress__delete(struct ui_progress *self);
+extern char ui_helpline__last_msg[];
+int ui_helpline__show_help(const char *format, va_list ap);
+#include "ui/progress.h"
 #endif
 
 #endif /* __PERF_DEBUG_H */
index e7263d49bcf0e3041c359e722201988f2da79995..be22ae6ef0558009c0a1faaa4f55bcf2c5d828ca 100644 (file)
@@ -876,6 +876,9 @@ unsigned int hists__sort_list_width(struct hists *self)
                if (!se->elide)
                        ret += 2 + hists__col_len(self, se->se_width_idx);
 
+       if (verbose) /* Addr + origin */
+               ret += 3 + BITS_PER_LONG / 4;
+
        return ret;
 }
 
@@ -980,9 +983,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
        return 0;
 }
 
-static struct objdump_line *objdump_line__new(s64 offset, char *line)
+static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
 {
-       struct objdump_line *self = malloc(sizeof(*self));
+       struct objdump_line *self = malloc(sizeof(*self) + privsize);
 
        if (self != NULL) {
                self->offset = offset;
@@ -1014,7 +1017,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 }
 
 static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
-                                         struct list_head *head)
+                                         struct list_head *head, size_t privsize)
 {
        struct symbol *sym = self->ms.sym;
        struct objdump_line *objdump_line;
@@ -1065,7 +1068,7 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
                        offset = -1;
        }
 
-       objdump_line = objdump_line__new(offset, line);
+       objdump_line = objdump_line__new(offset, line, privsize);
        if (objdump_line == NULL) {
                free(line);
                return -1;
@@ -1075,7 +1078,8 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
        return 0;
 }
 
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
+int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
+                        size_t privsize)
 {
        struct symbol *sym = self->ms.sym;
        struct map *map = self->ms.map;
@@ -1140,7 +1144,7 @@ fallback:
                goto out_free_filename;
 
        while (!feof(file))
-               if (hist_entry__parse_objdump_line(self, file, head) < 0)
+               if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0)
                        break;
 
        pclose(file);
index 65a48db46a29f0b0766f43474271f6e935b3c952..587d375d34300daa09948c1a0d95407b4f8439fa 100644 (file)
@@ -101,7 +101,8 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
                      bool show_displacement, FILE *fp);
 
 int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip);
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head);
+int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
+                        size_t privsize);
 
 void hists__filter_by_dso(struct hists *self, const struct dso *dso);
 void hists__filter_by_thread(struct hists *self, const struct thread *thread);
index dbe4b814382ac03e754957848c2d3a763762cb5b..f5ca26e53fbbad820623472a052fa848a9311c0b 100644 (file)
@@ -15,4 +15,12 @@ static inline void list_del_range(struct list_head *begin,
        begin->prev->next = end->next;
        end->next->prev = begin->prev;
 }
+
+/**
+ * list_for_each_from  -       iterate over a list from one of its nodes
+ * @pos:  the &struct list_head to use as a loop cursor, from where to start
+ * @head: the head for your list.
+ */
+#define list_for_each_from(pos, head) \
+       for (; prefetch(pos->next), pos != (head); pos = pos->next)
 #endif
index 196862a81a218e8d3603db854e1263b9ce317963..12de3b8112f97a079841ad37832934d79cc53bce 100644 (file)
@@ -6,4 +6,16 @@
 #define DECLARE_BITMAP(name,bits) \
        unsigned long name[BITS_TO_LONGS(bits)]
 
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+struct hlist_head {
+       struct hlist_node *first;
+};
+
+struct hlist_node {
+       struct hlist_node *next, **pprev;
+};
+
 #endif
index 2e665cb84055042edcddb9bef62cf45d71cbe238..e72f05c3bef09258311f7192afb179a10657c450 100644 (file)
@@ -1606,8 +1606,10 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 
        /* Init vmlinux path */
        ret = init_vmlinux();
-       if (ret < 0)
+       if (ret < 0) {
+               free(pkgs);
                return ret;
+       }
 
        /* Loop 1: convert all events */
        for (i = 0; i < npevs; i++) {
@@ -1625,10 +1627,13 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
                ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
                                                pkgs[i].ntevs, force_add);
 end:
-       /* Loop 3: cleanup trace events  */
-       for (i = 0; i < npevs; i++)
+       /* Loop 3: cleanup and free trace events  */
+       for (i = 0; i < npevs; i++) {
                for (j = 0; j < pkgs[i].ntevs; j++)
                        clear_probe_trace_event(&pkgs[i].tevs[j]);
+               free(pkgs[i].tevs);
+       }
+       free(pkgs);
 
        return ret;
 }
index 840f1aabbb748b5cd9ef8c8e8b3cc722067b215e..525136684d4ec170201b4d07c7b080b73851edf9 100644 (file)
@@ -33,7 +33,6 @@
 #include <ctype.h>
 #include <dwarf-regs.h>
 
-#include "string.h"
 #include "event.h"
 #include "debug.h"
 #include "util.h"
@@ -706,8 +705,12 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
                pf->tvar->value = strdup(pf->pvar->var);
                if (pf->tvar->value == NULL)
                        return -ENOMEM;
-               else
-                       return 0;
+               if (pf->pvar->type) {
+                       pf->tvar->type = strdup(pf->pvar->type);
+                       if (pf->tvar->type == NULL)
+                               return -ENOMEM;
+               }
+               return 0;
        }
 
        pr_debug("Searching '%s' variable in context.\n",
index 5ad07023504bb834e6334bbc5628e269faaa21ce..4cedea59f518ce7c1fcb61b0368598453bdf3a63 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PERF_PSTACK_
 #define _PERF_PSTACK_
 
+#include <stdbool.h>
+
 struct pstack;
 struct pstack *pstack__new(unsigned short max_nr_entries);
 void pstack__delete(struct pstack *self);
index 1c61a4f4aa8affbf01df5992a50a149893257b68..b62a553cc67d969c104638b9bf33922f351f06bb 100644 (file)
@@ -196,7 +196,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
 
        if (verbose) {
                char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
-               ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o);
+               ret += repsep_snprintf(bf, size, "%*Lx %c ",
+                                      BITS_PER_LONG / 4, self->ip, o);
        }
 
        ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
@@ -204,7 +205,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
                ret += repsep_snprintf(bf + ret, size - ret, "%s",
                                       self->ms.sym->name);
        else
-               ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip);
+               ret += repsep_snprintf(bf + ret, size - ret, "%*Lx",
+                                      BITS_PER_LONG / 4, self->ip);
 
        return ret;
 }
index 6f0dd90c36ce75496e78e9be7662e08a7d000511..1a367734e01693c8a93f79bb3846af4a89f9cffe 100644 (file)
@@ -131,7 +131,8 @@ static void map_groups__fixup_end(struct map_groups *self)
                __map_groups__fixup_end(self, i);
 }
 
-static struct symbol *symbol__new(u64 start, u64 len, const char *name)
+static struct symbol *symbol__new(u64 start, u64 len, u8 binding,
+                                 const char *name)
 {
        size_t namelen = strlen(name) + 1;
        struct symbol *self = calloc(1, (symbol_conf.priv_size +
@@ -144,6 +145,7 @@ static struct symbol *symbol__new(u64 start, u64 len, const char *name)
 
        self->start   = start;
        self->end     = len ? start + len - 1 : start;
+       self->binding = binding;
        self->namelen = namelen - 1;
 
        pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);
@@ -160,8 +162,11 @@ void symbol__delete(struct symbol *self)
 
 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
 {
-       return fprintf(fp, " %llx-%llx %s\n",
-                      self->start, self->end, self->name);
+       return fprintf(fp, " %llx-%llx %c %s\n",
+                      self->start, self->end,
+                      self->binding == STB_GLOBAL ? 'g' :
+                      self->binding == STB_LOCAL  ? 'l' : 'w',
+                      self->name);
 }
 
 void dso__set_long_name(struct dso *self, char *name)
@@ -453,6 +458,14 @@ struct process_kallsyms_args {
        struct dso *dso;
 };
 
+static u8 kallsyms2elf_type(char type)
+{
+       if (type == 'W')
+               return STB_WEAK;
+
+       return isupper(type) ? STB_GLOBAL : STB_LOCAL;
+}
+
 static int map__process_kallsym_symbol(void *arg, const char *name,
                                       char type, u64 start)
 {
@@ -466,7 +479,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
        /*
         * Will fix up the end later, when we have all symbols sorted.
         */
-       sym = symbol__new(start, 0, name);
+       sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
 
        if (sym == NULL)
                return -ENOMEM;
@@ -661,7 +674,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map,
                if (len + 2 >= line_len)
                        continue;
 
-               sym = symbol__new(start, size, line + len);
+               sym = symbol__new(start, size, STB_GLOBAL, line + len);
 
                if (sym == NULL)
                        goto out_delete_line;
@@ -873,7 +886,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
                                 "%s@plt", elf_sym__name(&sym, symstrs));
 
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
-                                       sympltname);
+                                       STB_GLOBAL, sympltname);
                        if (!f)
                                goto out_elf_end;
 
@@ -895,7 +908,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
                                 "%s@plt", elf_sym__name(&sym, symstrs));
 
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
-                                       sympltname);
+                                       STB_GLOBAL, sympltname);
                        if (!f)
                                goto out_elf_end;
 
@@ -1066,6 +1079,16 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                if (!is_label && !elf_sym__is_a(&sym, map->type))
                        continue;
 
+               /* Reject ARM ELF "mapping symbols": these aren't unique and
+                * don't identify functions, so will confuse the profile
+                * output: */
+               if (ehdr.e_machine == EM_ARM) {
+                       if (!strcmp(elf_name, "$a") ||
+                           !strcmp(elf_name, "$d") ||
+                           !strcmp(elf_name, "$t"))
+                               continue;
+               }
+
                if (opdsec && sym.st_shndx == opdidx) {
                        u32 offset = sym.st_value - opdshdr.sh_addr;
                        u64 *opd = opddata->d_buf + offset;
@@ -1146,7 +1169,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
                if (demangled != NULL)
                        elf_name = demangled;
 new_symbol:
-               f = symbol__new(sym.st_value, sym.st_size, elf_name);
+               f = symbol__new(sym.st_value, sym.st_size,
+                               GELF_ST_BIND(sym.st_info), elf_name);
                free(demangled);
                if (!f)
                        goto out_elf_end;
index 906be20011d93ce7aeeea9d02c9026a3bf2db359..b7a8da4af5a0a98e84e1616e55cdaceec18fcdbf 100644 (file)
@@ -53,6 +53,7 @@ struct symbol {
        u64             start;
        u64             end;
        u16             namelen;
+       u8              binding;
        char            name[0];
 };
 
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
new file mode 100644 (file)
index 0000000..66f2d58
--- /dev/null
@@ -0,0 +1,329 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+/*
+ * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
+ * the build if it isn't defined. Use the equivalent one that glibc
+ * has on features.h.
+ */
+#include <features.h>
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
+#endif
+#include <slang.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <stdlib.h>
+#include <sys/ttydefaults.h>
+#include "browser.h"
+#include "helpline.h"
+#include "../color.h"
+#include "../util.h"
+
+#if SLANG_VERSION < 20104
+#define sltt_set_color(obj, name, fg, bg) \
+       SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
+#else
+#define sltt_set_color SLtt_set_color
+#endif
+
+newtComponent newt_form__new(void);
+
+int ui_browser__percent_color(double percent, bool current)
+{
+       if (current)
+               return HE_COLORSET_SELECTED;
+       if (percent >= MIN_RED)
+               return HE_COLORSET_TOP;
+       if (percent >= MIN_GREEN)
+               return HE_COLORSET_MEDIUM;
+       return HE_COLORSET_NORMAL;
+}
+
+void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
+{
+       struct list_head *head = self->entries;
+       struct list_head *pos;
+
+       switch (whence) {
+       case SEEK_SET:
+               pos = head->next;
+               break;
+       case SEEK_CUR:
+               pos = self->top;
+               break;
+       case SEEK_END:
+               pos = head->prev;
+               break;
+       default:
+               return;
+       }
+
+       if (offset > 0) {
+               while (offset-- != 0)
+                       pos = pos->next;
+       } else {
+               while (offset++ != 0)
+                       pos = pos->prev;
+       }
+
+       self->top = pos;
+}
+
+void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
+{
+       struct rb_root *root = self->entries;
+       struct rb_node *nd;
+
+       switch (whence) {
+       case SEEK_SET:
+               nd = rb_first(root);
+               break;
+       case SEEK_CUR:
+               nd = self->top;
+               break;
+       case SEEK_END:
+               nd = rb_last(root);
+               break;
+       default:
+               return;
+       }
+
+       if (offset > 0) {
+               while (offset-- != 0)
+                       nd = rb_next(nd);
+       } else {
+               while (offset++ != 0)
+                       nd = rb_prev(nd);
+       }
+
+       self->top = nd;
+}
+
+unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
+{
+       struct rb_node *nd;
+       int row = 0;
+
+       if (self->top == NULL)
+                self->top = rb_first(self->entries);
+
+       nd = self->top;
+
+       while (nd != NULL) {
+               SLsmg_gotorc(self->y + row, self->x);
+               self->write(self, nd, row);
+               if (++row == self->height)
+                       break;
+               nd = rb_next(nd);
+       }
+
+       return row;
+}
+
+bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
+{
+       return self->top_idx + row == self->index;
+}
+
+void ui_browser__refresh_dimensions(struct ui_browser *self)
+{
+       int cols, rows;
+       newtGetScreenSize(&cols, &rows);
+
+       if (self->width > cols - 4)
+               self->width = cols - 4;
+       self->height = rows - 5;
+       if (self->height > self->nr_entries)
+               self->height = self->nr_entries;
+       self->y  = (rows - self->height) / 2;
+       self->x = (cols - self->width) / 2;
+}
+
+void ui_browser__reset_index(struct ui_browser *self)
+{
+       self->index = self->top_idx = 0;
+       self->seek(self, 0, SEEK_SET);
+}
+
+int ui_browser__show(struct ui_browser *self, const char *title,
+                    const char *helpline, ...)
+{
+       va_list ap;
+
+       if (self->form != NULL) {
+               newtFormDestroy(self->form);
+               newtPopWindow();
+       }
+       ui_browser__refresh_dimensions(self);
+       newtCenteredWindow(self->width, self->height, title);
+       self->form = newt_form__new();
+       if (self->form == NULL)
+               return -1;
+
+       self->sb = newtVerticalScrollbar(self->width, 0, self->height,
+                                        HE_COLORSET_NORMAL,
+                                        HE_COLORSET_SELECTED);
+       if (self->sb == NULL)
+               return -1;
+
+       newtFormAddHotKey(self->form, NEWT_KEY_UP);
+       newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
+       newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
+       newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
+       newtFormAddHotKey(self->form, NEWT_KEY_HOME);
+       newtFormAddHotKey(self->form, NEWT_KEY_END);
+       newtFormAddHotKey(self->form, ' ');
+       newtFormAddComponent(self->form, self->sb);
+
+       va_start(ap, helpline);
+       ui_helpline__vpush(helpline, ap);
+       va_end(ap);
+       return 0;
+}
+
+void ui_browser__hide(struct ui_browser *self)
+{
+       newtFormDestroy(self->form);
+       newtPopWindow();
+       self->form = NULL;
+       ui_helpline__pop();
+}
+
+int ui_browser__refresh(struct ui_browser *self)
+{
+       int row;
+
+       newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
+       row = self->refresh(self);
+       SLsmg_set_color(HE_COLORSET_NORMAL);
+       SLsmg_fill_region(self->y + row, self->x,
+                         self->height - row, self->width, ' ');
+
+       return 0;
+}
+
+int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
+{
+       if (ui_browser__refresh(self) < 0)
+               return -1;
+
+       while (1) {
+               off_t offset;
+
+               newtFormRun(self->form, es);
+
+               if (es->reason != NEWT_EXIT_HOTKEY)
+                       break;
+               if (is_exit_key(es->u.key))
+                       return es->u.key;
+               switch (es->u.key) {
+               case NEWT_KEY_DOWN:
+                       if (self->index == self->nr_entries - 1)
+                               break;
+                       ++self->index;
+                       if (self->index == self->top_idx + self->height) {
+                               ++self->top_idx;
+                               self->seek(self, +1, SEEK_CUR);
+                       }
+                       break;
+               case NEWT_KEY_UP:
+                       if (self->index == 0)
+                               break;
+                       --self->index;
+                       if (self->index < self->top_idx) {
+                               --self->top_idx;
+                               self->seek(self, -1, SEEK_CUR);
+                       }
+                       break;
+               case NEWT_KEY_PGDN:
+               case ' ':
+                       if (self->top_idx + self->height > self->nr_entries - 1)
+                               break;
+
+                       offset = self->height;
+                       if (self->index + offset > self->nr_entries - 1)
+                               offset = self->nr_entries - 1 - self->index;
+                       self->index += offset;
+                       self->top_idx += offset;
+                       self->seek(self, +offset, SEEK_CUR);
+                       break;
+               case NEWT_KEY_PGUP:
+                       if (self->top_idx == 0)
+                               break;
+
+                       if (self->top_idx < self->height)
+                               offset = self->top_idx;
+                       else
+                               offset = self->height;
+
+                       self->index -= offset;
+                       self->top_idx -= offset;
+                       self->seek(self, -offset, SEEK_CUR);
+                       break;
+               case NEWT_KEY_HOME:
+                       ui_browser__reset_index(self);
+                       break;
+               case NEWT_KEY_END:
+                       offset = self->height - 1;
+                       if (offset >= self->nr_entries)
+                               offset = self->nr_entries - 1;
+
+                       self->index = self->nr_entries - 1;
+                       self->top_idx = self->index - offset;
+                       self->seek(self, -offset, SEEK_END);
+                       break;
+               default:
+                       return es->u.key;
+               }
+               if (ui_browser__refresh(self) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
+{
+       struct list_head *pos;
+       struct list_head *head = self->entries;
+       int row = 0;
+
+       if (self->top == NULL || self->top == self->entries)
+                self->top = head->next;
+
+       pos = self->top;
+
+       list_for_each_from(pos, head) {
+               SLsmg_gotorc(self->y + row, self->x);
+               self->write(self, pos, row);
+               if (++row == self->height)
+                       break;
+       }
+
+       return row;
+}
+
+static struct newtPercentTreeColors {
+       const char *topColorFg, *topColorBg;
+       const char *mediumColorFg, *mediumColorBg;
+       const char *normalColorFg, *normalColorBg;
+       const char *selColorFg, *selColorBg;
+       const char *codeColorFg, *codeColorBg;
+} defaultPercentTreeColors = {
+       "red",       "lightgray",
+       "green",     "lightgray",
+       "black",     "lightgray",
+       "lightgray", "magenta",
+       "blue",      "lightgray",
+};
+
+void ui_browser__init(void)
+{
+       struct newtPercentTreeColors *c = &defaultPercentTreeColors;
+
+       sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
+       sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
+       sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
+       sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
+       sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
+}
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
new file mode 100644 (file)
index 0000000..0b9f829
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _PERF_UI_BROWSER_H_
+#define _PERF_UI_BROWSER_H_ 1
+
+#include <stdbool.h>
+#include <newt.h>
+#include <sys/types.h>
+#include "../types.h"
+
+#define HE_COLORSET_TOP                50
+#define HE_COLORSET_MEDIUM     51
+#define HE_COLORSET_NORMAL     52
+#define HE_COLORSET_SELECTED   53
+#define HE_COLORSET_CODE       54
+
+struct ui_browser {
+       newtComponent form, sb;
+       u64           index, top_idx;
+       void          *top, *entries;
+       u16           y, x, width, height;
+       void          *priv;
+       unsigned int  (*refresh)(struct ui_browser *self);
+       void          (*write)(struct ui_browser *self, void *entry, int row);
+       void          (*seek)(struct ui_browser *self, off_t offset, int whence);
+       u32           nr_entries;
+};
+
+
+int ui_browser__percent_color(double percent, bool current);
+bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
+void ui_browser__refresh_dimensions(struct ui_browser *self);
+void ui_browser__reset_index(struct ui_browser *self);
+
+int ui_browser__show(struct ui_browser *self, const char *title,
+                    const char *helpline, ...);
+void ui_browser__hide(struct ui_browser *self);
+int ui_browser__refresh(struct ui_browser *self);
+int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es);
+
+void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
+unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
+
+void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence);
+unsigned int ui_browser__list_head_refresh(struct ui_browser *self);
+
+void ui_browser__init(void);
+#endif /* _PERF_UI_BROWSER_H_ */
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
new file mode 100644 (file)
index 0000000..55ff792
--- /dev/null
@@ -0,0 +1,240 @@
+#include "../browser.h"
+#include "../helpline.h"
+#include "../libslang.h"
+#include "../../hist.h"
+#include "../../sort.h"
+#include "../../symbol.h"
+
+static void ui__error_window(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
+       va_end(ap);
+}
+
+struct annotate_browser {
+       struct ui_browser b;
+       struct rb_root    entries;
+       struct rb_node    *curr_hot;
+};
+
+struct objdump_line_rb_node {
+       struct rb_node  rb_node;
+       double          percent;
+       u32             idx;
+};
+
+static inline
+struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
+{
+       return (struct objdump_line_rb_node *)(self + 1);
+}
+
+static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
+{
+       struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);
+       bool current_entry = ui_browser__is_current_entry(self, row);
+       int width = self->width;
+
+       if (ol->offset != -1) {
+               struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
+               int color = ui_browser__percent_color(olrb->percent, current_entry);
+               SLsmg_set_color(color);
+               slsmg_printf(" %7.2f ", olrb->percent);
+               if (!current_entry)
+                       SLsmg_set_color(HE_COLORSET_CODE);
+       } else {
+               int color = ui_browser__percent_color(0, current_entry);
+               SLsmg_set_color(color);
+               slsmg_write_nstring(" ", 9);
+       }
+
+       SLsmg_write_char(':');
+       slsmg_write_nstring(" ", 8);
+       if (!*ol->line)
+               slsmg_write_nstring(" ", width - 18);
+       else
+               slsmg_write_nstring(ol->line, width - 18);
+}
+
+static double objdump_line__calc_percent(struct objdump_line *self,
+                                        struct list_head *head,
+                                        struct symbol *sym)
+{
+       double percent = 0.0;
+
+       if (self->offset != -1) {
+               int len = sym->end - sym->start;
+               unsigned int hits = 0;
+               struct sym_priv *priv = symbol__priv(sym);
+               struct sym_ext *sym_ext = priv->ext;
+               struct sym_hist *h = priv->hist;
+               s64 offset = self->offset;
+               struct objdump_line *next = objdump__get_next_ip_line(head, self);
+
+
+               while (offset < (s64)len &&
+                      (next == NULL || offset < next->offset)) {
+                       if (sym_ext) {
+                               percent += sym_ext[offset].percent;
+                       } else
+                               hits += h->ip[offset];
+
+                       ++offset;
+               }
+
+               if (sym_ext == NULL && h->sum)
+                       percent = 100.0 * hits / h->sum;
+       }
+
+       return percent;
+}
+
+static void objdump__insert_line(struct rb_root *self,
+                                struct objdump_line_rb_node *line)
+{
+       struct rb_node **p = &self->rb_node;
+       struct rb_node *parent = NULL;
+       struct objdump_line_rb_node *l;
+
+       while (*p != NULL) {
+               parent = *p;
+               l = rb_entry(parent, struct objdump_line_rb_node, rb_node);
+               if (line->percent < l->percent)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+       rb_link_node(&line->rb_node, parent, p);
+       rb_insert_color(&line->rb_node, self);
+}
+
+static void annotate_browser__set_top(struct annotate_browser *self,
+                                     struct rb_node *nd)
+{
+       struct objdump_line_rb_node *rbpos;
+       struct objdump_line *pos;
+       unsigned back;
+
+       ui_browser__refresh_dimensions(&self->b);
+       back = self->b.height / 2;
+       rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node);
+       pos = ((struct objdump_line *)rbpos) - 1;
+       self->b.top_idx = self->b.index = rbpos->idx;
+
+       while (self->b.top_idx != 0 && back != 0) {
+               pos = list_entry(pos->node.prev, struct objdump_line, node);
+
+               --self->b.top_idx;
+               --back;
+       }
+
+       self->b.top = pos;
+       self->curr_hot = nd;
+}
+
+static int annotate_browser__run(struct annotate_browser *self,
+                                struct newtExitStruct *es)
+{
+       struct rb_node *nd;
+       struct hist_entry *he = self->b.priv;
+
+       if (ui_browser__show(&self->b, he->ms.sym->name,
+                            "<- or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
+               return -1;
+
+       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
+
+       nd = self->curr_hot;
+       if (nd) {
+               newtFormAddHotKey(self->b.form, NEWT_KEY_TAB);
+               newtFormAddHotKey(self->b.form, NEWT_KEY_UNTAB);
+       }
+
+       while (1) {
+               ui_browser__run(&self->b, es);
+
+               if (es->reason != NEWT_EXIT_HOTKEY)
+                       break;
+
+               switch (es->u.key) {
+               case NEWT_KEY_TAB:
+                       nd = rb_prev(nd);
+                       if (nd == NULL)
+                               nd = rb_last(&self->entries);
+                       annotate_browser__set_top(self, nd);
+                       break;
+               case NEWT_KEY_UNTAB:
+                       nd = rb_next(nd);
+                       if (nd == NULL)
+                               nd = rb_first(&self->entries);
+                       annotate_browser__set_top(self, nd);
+                       break;
+               default:
+                       goto out;
+               }
+       }
+out:
+       ui_browser__hide(&self->b);
+       return 0;
+}
+
+int hist_entry__tui_annotate(struct hist_entry *self)
+{
+       struct newtExitStruct es;
+       struct objdump_line *pos, *n;
+       struct objdump_line_rb_node *rbpos;
+       LIST_HEAD(head);
+       struct annotate_browser browser = {
+               .b = {
+                       .entries = &head,
+                       .refresh = ui_browser__list_head_refresh,
+                       .seek    = ui_browser__list_head_seek,
+                       .write   = annotate_browser__write,
+                       .priv    = self,
+               },
+       };
+       int ret;
+
+       if (self->ms.sym == NULL)
+               return -1;
+
+       if (self->ms.map->dso->annotate_warned)
+               return -1;
+
+       if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) {
+               ui__error_window(ui_helpline__last_msg);
+               return -1;
+       }
+
+       ui_helpline__push("Press <- or ESC to exit");
+
+       list_for_each_entry(pos, &head, node) {
+               size_t line_len = strlen(pos->line);
+               if (browser.b.width < line_len)
+                       browser.b.width = line_len;
+               rbpos = objdump_line__rb(pos);
+               rbpos->idx = browser.b.nr_entries++;
+               rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
+               if (rbpos->percent < 0.01)
+                       continue;
+               objdump__insert_line(&browser.entries, rbpos);
+       }
+
+       /*
+        * Position the browser at the hottest line.
+        */
+       browser.curr_hot = rb_last(&browser.entries);
+       if (browser.curr_hot)
+               annotate_browser__set_top(&browser, browser.curr_hot);
+
+       browser.b.width += 18; /* Percentage */
+       ret = annotate_browser__run(&browser, &es);
+       list_for_each_entry_safe(pos, n, &head, node) {
+               list_del(&pos->node);
+               objdump_line__free(pos);
+       }
+       return ret;
+}
similarity index 56%
rename from tools/perf/util/newt.c
rename to tools/perf/util/ui/browsers/hists.c
index 91de99b58445b7b4ac798c40c6e3a3583405d6df..dafdf6775d77f44d69abf1980b1a9cfe4ab053dc 100644 (file)
 #define _GNU_SOURCE
 #include <stdio.h>
 #undef _GNU_SOURCE
-/*
- * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
- * the build if it isn't defined. Use the equivalent one that glibc
- * has on features.h.
- */
-#include <features.h>
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
-#endif
-#include <slang.h>
-#include <signal.h>
+#include "../libslang.h"
 #include <stdlib.h>
+#include <string.h>
 #include <newt.h>
-#include <sys/ttydefaults.h>
-
-#include "cache.h"
-#include "hist.h"
-#include "pstack.h"
-#include "session.h"
-#include "sort.h"
-#include "symbol.h"
-
-#if SLANG_VERSION < 20104
-#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args)
-#define slsmg_write_nstring(msg, len) SLsmg_write_nstring((char *)msg, len)
-#define sltt_set_color(obj, name, fg, bg) SLtt_set_color(obj,(char *)name,\
-                                                        (char *)fg, (char *)bg)
-#else
-#define slsmg_printf SLsmg_printf
-#define slsmg_write_nstring SLsmg_write_nstring
-#define sltt_set_color SLtt_set_color
-#endif
-
-struct ui_progress {
-       newtComponent form, scale;
-};
+#include <linux/rbtree.h>
 
-struct ui_progress *ui_progress__new(const char *title, u64 total)
-{
-       struct ui_progress *self = malloc(sizeof(*self));
-
-       if (self != NULL) {
-               int cols;
-
-               if (use_browser <= 0)   
-                       return self;
-               newtGetScreenSize(&cols, NULL);
-               cols -= 4;
-               newtCenteredWindow(cols, 1, title);
-               self->form  = newtForm(NULL, NULL, 0);
-               if (self->form == NULL)
-                       goto out_free_self;
-               self->scale = newtScale(0, 0, cols, total);
-               if (self->scale == NULL)
-                       goto out_free_form;
-               newtFormAddComponent(self->form, self->scale);
-               newtRefresh();
-       }
+#include "../../hist.h"
+#include "../../pstack.h"
+#include "../../sort.h"
+#include "../../util.h"
 
-       return self;
+#include "../browser.h"
+#include "../helpline.h"
+#include "../util.h"
+#include "map.h"
 
-out_free_form:
-       newtFormDestroy(self->form);
-out_free_self:
-       free(self);
-       return NULL;
-}
+struct hist_browser {
+       struct ui_browser   b;
+       struct hists        *hists;
+       struct hist_entry   *he_selection;
+       struct map_symbol   *selection;
+};
 
-void ui_progress__update(struct ui_progress *self, u64 curr)
+static void hist_browser__refresh_dimensions(struct hist_browser *self)
 {
-       /*
-        * FIXME: We should have a per UI backend way of showing progress,
-        * stdio will just show a percentage as NN%, etc.
-        */
-       if (use_browser <= 0)
-               return;
-       newtScaleSet(self->scale, curr);
-       newtRefresh();
+       /* 3 == +/- toggle symbol before actual hist_entry rendering */
+       self->b.width = 3 + (hists__sort_list_width(self->hists) +
+                            sizeof("[k]"));
 }
 
-void ui_progress__delete(struct ui_progress *self)
+static void hist_browser__reset(struct hist_browser *self)
 {
-       if (use_browser > 0) {
-               newtFormDestroy(self->form);
-               newtPopWindow();
-       }
-       free(self);
+       self->b.nr_entries = self->hists->nr_entries;
+       hist_browser__refresh_dimensions(self);
+       ui_browser__reset_index(&self->b);
 }
 
-static void ui_helpline__pop(void)
+static char tree__folded_sign(bool unfolded)
 {
-       newtPopHelpLine();
+       return unfolded ? '-' : '+';
 }
 
-static void ui_helpline__push(const char *msg)
+static char map_symbol__folded(const struct map_symbol *self)
 {
-       newtPushHelpLine(msg);
+       return self->has_children ? tree__folded_sign(self->unfolded) : ' ';
 }
 
-static void ui_helpline__vpush(const char *fmt, va_list ap)
+static char hist_entry__folded(const struct hist_entry *self)
 {
-       char *s;
-
-       if (vasprintf(&s, fmt, ap) < 0)
-               vfprintf(stderr, fmt, ap);
-       else {
-               ui_helpline__push(s);
-               free(s);
-       }
+       return map_symbol__folded(&self->ms);
 }
 
-static void ui_helpline__fpush(const char *fmt, ...)
+static char callchain_list__folded(const struct callchain_list *self)
 {
-       va_list ap;
-
-       va_start(ap, fmt);
-       ui_helpline__vpush(fmt, ap);
-       va_end(ap);
+       return map_symbol__folded(&self->ms);
 }
 
-static void ui_helpline__puts(const char *msg)
+static int callchain_node__count_rows_rb_tree(struct callchain_node *self)
 {
-       ui_helpline__pop();
-       ui_helpline__push(msg);
-}
-
-static char browser__last_msg[1024];
+       int n = 0;
+       struct rb_node *nd;
 
-int browser__show_help(const char *format, va_list ap)
-{
-       int ret;
-       static int backlog;
+       for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
+               struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
+               struct callchain_list *chain;
+               char folded_sign = ' '; /* No children */
 
-        ret = vsnprintf(browser__last_msg + backlog,
-                       sizeof(browser__last_msg) - backlog, format, ap);
-       backlog += ret;
+               list_for_each_entry(chain, &child->val, list) {
+                       ++n;
+                       /* We need this because we may not have children */
+                       folded_sign = callchain_list__folded(chain);
+                       if (folded_sign == '+')
+                               break;
+               }
 
-       if (browser__last_msg[backlog - 1] == '\n') {
-               ui_helpline__puts(browser__last_msg);
-               newtRefresh();
-               backlog = 0;
+               if (folded_sign == '-') /* Have children and they're unfolded */
+                       n += callchain_node__count_rows_rb_tree(child);
        }
 
-       return ret;
-}
-
-static void newt_form__set_exit_keys(newtComponent self)
-{
-       newtFormAddHotKey(self, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
-       newtFormAddHotKey(self, 'Q');
-       newtFormAddHotKey(self, 'q');
-       newtFormAddHotKey(self, CTRL('c'));
-}
-
-static newtComponent newt_form__new(void)
-{
-       newtComponent self = newtForm(NULL, NULL, 0);
-       if (self)
-               newt_form__set_exit_keys(self);
-       return self;
+       return n;
 }
 
-static int popup_menu(int argc, char * const argv[])
+static int callchain_node__count_rows(struct callchain_node *node)
 {
-       struct newtExitStruct es;
-       int i, rc = -1, max_len = 5;
-       newtComponent listbox, form = newt_form__new();
-
-       if (form == NULL)
-               return -1;
-
-       listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT);
-       if (listbox == NULL)
-               goto out_destroy_form;
-
-       newtFormAddComponent(form, listbox);
+       struct callchain_list *chain;
+       bool unfolded = false;
+       int n = 0;
 
-       for (i = 0; i < argc; ++i) {
-               int len = strlen(argv[i]);
-               if (len > max_len)
-                       max_len = len;
-               if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i))
-                       goto out_destroy_form;
+       list_for_each_entry(chain, &node->val, list) {
+               ++n;
+               unfolded = chain->ms.unfolded;
        }
 
-       newtCenteredWindow(max_len, argc, NULL);
-       newtFormRun(form, &es);
-       rc = newtListboxGetCurrent(listbox) - NULL;
-       if (es.reason == NEWT_EXIT_HOTKEY)
-               rc = -1;
-       newtPopWindow();
-out_destroy_form:
-       newtFormDestroy(form);
-       return rc;
+       if (unfolded)
+               n += callchain_node__count_rows_rb_tree(node);
+
+       return n;
 }
 
-static int ui__help_window(const char *text)
+static int callchain__count_rows(struct rb_root *chain)
 {
-       struct newtExitStruct es;
-       newtComponent tb, form = newt_form__new();
-       int rc = -1;
-       int max_len = 0, nr_lines = 0;
-       const char *t;
-
-       if (form == NULL)
-               return -1;
+       struct rb_node *nd;
+       int n = 0;
 
-       t = text;
-       while (1) {
-               const char *sep = strchr(t, '\n');
-               int len;
-
-               if (sep == NULL)
-                       sep = strchr(t, '\0');
-               len = sep - t;
-               if (max_len < len)
-                       max_len = len;
-               ++nr_lines;
-               if (*sep == '\0')
-                       break;
-               t = sep + 1;
+       for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
+               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+               n += callchain_node__count_rows(node);
        }
 
-       tb = newtTextbox(0, 0, max_len, nr_lines, 0);
-       if (tb == NULL)
-               goto out_destroy_form;
-
-       newtTextboxSetText(tb, text);
-       newtFormAddComponent(form, tb);
-       newtCenteredWindow(max_len, nr_lines, NULL);
-       newtFormRun(form, &es);
-       newtPopWindow();
-       rc = 0;
-out_destroy_form:
-       newtFormDestroy(form);
-       return rc;
-}
-
-static bool dialog_yesno(const char *msg)
-{
-       /* newtWinChoice should really be accepting const char pointers... */
-       char yes[] = "Yes", no[] = "No";
-       return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
+       return n;
 }
 
-static void ui__error_window(const char *fmt, ...)
+static bool map_symbol__toggle_fold(struct map_symbol *self)
 {
-       va_list ap;
+       if (!self->has_children)
+               return false;
 
-       va_start(ap, fmt);
-       newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
-       va_end(ap);
+       self->unfolded = !self->unfolded;
+       return true;
 }
 
-#define HE_COLORSET_TOP                50
-#define HE_COLORSET_MEDIUM     51
-#define HE_COLORSET_NORMAL     52
-#define HE_COLORSET_SELECTED   53
-#define HE_COLORSET_CODE       54
-
-static int ui_browser__percent_color(double percent, bool current)
+static void callchain_node__init_have_children_rb_tree(struct callchain_node *self)
 {
-       if (current)
-               return HE_COLORSET_SELECTED;
-       if (percent >= MIN_RED)
-               return HE_COLORSET_TOP;
-       if (percent >= MIN_GREEN)
-               return HE_COLORSET_MEDIUM;
-       return HE_COLORSET_NORMAL;
-}
-
-struct ui_browser {
-       newtComponent   form, sb;
-       u64             index, first_visible_entry_idx;
-       void            *first_visible_entry, *entries;
-       u16             top, left, width, height;
-       void            *priv;
-       unsigned int    (*refresh_entries)(struct ui_browser *self);
-       void            (*seek)(struct ui_browser *self,
-                               off_t offset, int whence);
-       u32             nr_entries;
-};
+       struct rb_node *nd = rb_first(&self->rb_root);
 
-static void ui_browser__list_head_seek(struct ui_browser *self,
-                                      off_t offset, int whence)
-{
-       struct list_head *head = self->entries;
-       struct list_head *pos;
+       for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
+               struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
+               struct callchain_list *chain;
+               int first = true;
 
-       switch (whence) {
-       case SEEK_SET:
-               pos = head->next;
-               break;
-       case SEEK_CUR:
-               pos = self->first_visible_entry;
-               break;
-       case SEEK_END:
-               pos = head->prev;
-               break;
-       default:
-               return;
-       }
+               list_for_each_entry(chain, &child->val, list) {
+                       if (first) {
+                               first = false;
+                               chain->ms.has_children = chain->list.next != &child->val ||
+                                                        rb_first(&child->rb_root) != NULL;
+                       } else
+                               chain->ms.has_children = chain->list.next == &child->val &&
+                                                        rb_first(&child->rb_root) != NULL;
+               }
 
-       if (offset > 0) {
-               while (offset-- != 0)
-                       pos = pos->next;
-       } else {
-               while (offset++ != 0)
-                       pos = pos->prev;
+               callchain_node__init_have_children_rb_tree(child);
        }
-
-       self->first_visible_entry = pos;
 }
 
-static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
+static void callchain_node__init_have_children(struct callchain_node *self)
 {
-       return (self->first_visible_entry_idx + row) == self->index;
-}
+       struct callchain_list *chain;
 
-static void ui_browser__refresh_dimensions(struct ui_browser *self)
-{
-       int cols, rows;
-       newtGetScreenSize(&cols, &rows);
-
-       if (self->width > cols - 4)
-               self->width = cols - 4;
-       self->height = rows - 5;
-       if (self->height > self->nr_entries)
-               self->height = self->nr_entries;
-       self->top  = (rows - self->height) / 2;
-       self->left = (cols - self->width) / 2;
+       list_for_each_entry(chain, &self->val, list)
+               chain->ms.has_children = rb_first(&self->rb_root) != NULL;
+
+       callchain_node__init_have_children_rb_tree(self);
 }
 
-static void ui_browser__reset_index(struct ui_browser *self)
+static void callchain__init_have_children(struct rb_root *self)
 {
-       self->index = self->first_visible_entry_idx = 0;
-       self->seek(self, 0, SEEK_SET);
+       struct rb_node *nd;
+
+       for (nd = rb_first(self); nd; nd = rb_next(nd)) {
+               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+               callchain_node__init_have_children(node);
+       }
 }
 
-static int ui_browser__show(struct ui_browser *self, const char *title)
+static void hist_entry__init_have_children(struct hist_entry *self)
 {
-       if (self->form != NULL) {
-               newtFormDestroy(self->form);
-               newtPopWindow();
+       if (!self->init_have_children) {
+               callchain__init_have_children(&self->sorted_chain);
+               self->init_have_children = true;
        }
-       ui_browser__refresh_dimensions(self);
-       newtCenteredWindow(self->width, self->height, title);
-       self->form = newt_form__new();
-       if (self->form == NULL)
-               return -1;
-
-       self->sb = newtVerticalScrollbar(self->width, 0, self->height,
-                                        HE_COLORSET_NORMAL,
-                                        HE_COLORSET_SELECTED);
-       if (self->sb == NULL)
-               return -1;
-
-       newtFormAddHotKey(self->form, NEWT_KEY_UP);
-       newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
-       newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
-       newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
-       newtFormAddHotKey(self->form, NEWT_KEY_HOME);
-       newtFormAddHotKey(self->form, NEWT_KEY_END);
-       newtFormAddComponent(self->form, self->sb);
-       return 0;
 }
 
-static int objdump_line__show(struct objdump_line *self, struct list_head *head,
-                             int width, struct hist_entry *he, int len,
-                             bool current_entry)
+static bool hist_browser__toggle_fold(struct hist_browser *self)
 {
-       if (self->offset != -1) {
-               struct symbol *sym = he->ms.sym;
-               unsigned int hits = 0;
-               double percent = 0.0;
-               int color;
-               struct sym_priv *priv = symbol__priv(sym);
-               struct sym_ext *sym_ext = priv->ext;
-               struct sym_hist *h = priv->hist;
-               s64 offset = self->offset;
-               struct objdump_line *next = objdump__get_next_ip_line(head, self);
-
-               while (offset < (s64)len &&
-                      (next == NULL || offset < next->offset)) {
-                       if (sym_ext) {
-                               percent += sym_ext[offset].percent;
-                       } else
-                               hits += h->ip[offset];
+       if (map_symbol__toggle_fold(self->selection)) {
+               struct hist_entry *he = self->he_selection;
 
-                       ++offset;
-               }
+               hist_entry__init_have_children(he);
+               self->hists->nr_entries -= he->nr_rows;
 
-               if (sym_ext == NULL && h->sum)
-                       percent = 100.0 * hits / h->sum;
+               if (he->ms.unfolded)
+                       he->nr_rows = callchain__count_rows(&he->sorted_chain);
+               else
+                       he->nr_rows = 0;
+               self->hists->nr_entries += he->nr_rows;
+               self->b.nr_entries = self->hists->nr_entries;
 
-               color = ui_browser__percent_color(percent, current_entry);
-               SLsmg_set_color(color);
-               slsmg_printf(" %7.2f ", percent);
-               if (!current_entry)
-                       SLsmg_set_color(HE_COLORSET_CODE);
-       } else {
-               int color = ui_browser__percent_color(0, current_entry);
-               SLsmg_set_color(color);
-               slsmg_write_nstring(" ", 9);
+               return true;
        }
 
-       SLsmg_write_char(':');
-       slsmg_write_nstring(" ", 8);
-       if (!*self->line)
-               slsmg_write_nstring(" ", width - 18);
-       else
-               slsmg_write_nstring(self->line, width - 18);
-
-       return 0;
+       /* If it doesn't have children, no toggling performed */
+       return false;
 }
 
-static int ui_browser__refresh_entries(struct ui_browser *self)
+static int hist_browser__run(struct hist_browser *self, const char *title,
+                            struct newtExitStruct *es)
 {
-       int row;
+       char str[256], unit;
+       unsigned long nr_events = self->hists->stats.nr_events[PERF_RECORD_SAMPLE];
 
-       newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
-       row = self->refresh_entries(self);
-       SLsmg_set_color(HE_COLORSET_NORMAL);
-       SLsmg_fill_region(self->top + row, self->left,
-                         self->height - row, self->width, ' ');
+       self->b.entries = &self->hists->entries;
+       self->b.nr_entries = self->hists->nr_entries;
 
-       return 0;
-}
+       hist_browser__refresh_dimensions(self);
 
-static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
-{
-       if (ui_browser__refresh_entries(self) < 0)
+       nr_events = convert_unit(nr_events, &unit);
+       snprintf(str, sizeof(str), "Events: %lu%c                            ",
+                nr_events, unit);
+       newtDrawRootText(0, 0, str);
+
+       if (ui_browser__show(&self->b, title,
+                            "Press '?' for help on key bindings") < 0)
                return -1;
 
-       while (1) {
-               off_t offset;
+       newtFormAddHotKey(self->b.form, 'a');
+       newtFormAddHotKey(self->b.form, '?');
+       newtFormAddHotKey(self->b.form, 'h');
+       newtFormAddHotKey(self->b.form, 'd');
+       newtFormAddHotKey(self->b.form, 'D');
+       newtFormAddHotKey(self->b.form, 't');
+
+       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
+       newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT);
+       newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
 
-               newtFormRun(self->form, es);
+       while (1) {
+               ui_browser__run(&self->b, es);
 
                if (es->reason != NEWT_EXIT_HOTKEY)
                        break;
-               if (is_exit_key(es->u.key))
-                       return es->u.key;
                switch (es->u.key) {
-               case NEWT_KEY_DOWN:
-                       if (self->index == self->nr_entries - 1)
-                               break;
-                       ++self->index;
-                       if (self->index == self->first_visible_entry_idx + self->height) {
-                               ++self->first_visible_entry_idx;
-                               self->seek(self, +1, SEEK_CUR);
-                       }
-                       break;
-               case NEWT_KEY_UP:
-                       if (self->index == 0)
-                               break;
-                       --self->index;
-                       if (self->index < self->first_visible_entry_idx) {
-                               --self->first_visible_entry_idx;
-                               self->seek(self, -1, SEEK_CUR);
-                       }
-                       break;
-               case NEWT_KEY_PGDN:
-               case ' ':
-                       if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
-                               break;
-
-                       offset = self->height;
-                       if (self->index + offset > self->nr_entries - 1)
-                               offset = self->nr_entries - 1 - self->index;
-                       self->index += offset;
-                       self->first_visible_entry_idx += offset;
-                       self->seek(self, +offset, SEEK_CUR);
-                       break;
-               case NEWT_KEY_PGUP:
-                       if (self->first_visible_entry_idx == 0)
+               case 'D': { /* Debug */
+                       static int seq;
+                       struct hist_entry *h = rb_entry(self->b.top,
+                                                       struct hist_entry, rb_node);
+                       ui_helpline__pop();
+                       ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
+                                          seq++, self->b.nr_entries,
+                                          self->hists->nr_entries,
+                                          self->b.height,
+                                          self->b.index,
+                                          self->b.top_idx,
+                                          h->row_offset, h->nr_rows);
+               }
+                       continue;
+               case NEWT_KEY_ENTER:
+                       if (hist_browser__toggle_fold(self))
                                break;
-
-                       if (self->first_visible_entry_idx < self->height)
-                               offset = self->first_visible_entry_idx;
-                       else
-                               offset = self->height;
-
-                       self->index -= offset;
-                       self->first_visible_entry_idx -= offset;
-                       self->seek(self, -offset, SEEK_CUR);
-                       break;
-               case NEWT_KEY_HOME:
-                       ui_browser__reset_index(self);
-                       break;
-               case NEWT_KEY_END:
-                       offset = self->height - 1;
-                       if (offset >= self->nr_entries)
-                               offset = self->nr_entries - 1;
-
-                       self->index = self->nr_entries - 1;
-                       self->first_visible_entry_idx = self->index - offset;
-                       self->seek(self, -offset, SEEK_END);
-                       break;
+                       /* fall thru */
                default:
-                       return es->u.key;
+                       return 0;
                }
-               if (ui_browser__refresh_entries(self) < 0)
-                       return -1;
        }
+
+       ui_browser__hide(&self->b);
        return 0;
 }
 
@@ -520,469 +269,14 @@ static char *callchain_list__sym_name(struct callchain_list *self,
        return bf;
 }
 
-static unsigned int hist_entry__annotate_browser_refresh(struct ui_browser *self)
-{
-       struct objdump_line *pos;
-       struct list_head *head = self->entries;
-       struct hist_entry *he = self->priv;
-       int row = 0;
-       int len = he->ms.sym->end - he->ms.sym->start;
-
-       if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries)
-                self->first_visible_entry = head->next;
-
-       pos = list_entry(self->first_visible_entry, struct objdump_line, node);
-
-       list_for_each_entry_from(pos, head, node) {
-               bool current_entry = ui_browser__is_current_entry(self, row);
-               SLsmg_gotorc(self->top + row, self->left);
-               objdump_line__show(pos, head, self->width,
-                                  he, len, current_entry);
-               if (++row == self->height)
-                       break;
-       }
-
-       return row;
-}
+#define LEVEL_OFFSET_STEP 3
 
-int hist_entry__tui_annotate(struct hist_entry *self)
-{
-       struct ui_browser browser;
-       struct newtExitStruct es;
-       struct objdump_line *pos, *n;
-       LIST_HEAD(head);
-       int ret;
-
-       if (self->ms.sym == NULL)
-               return -1;
-
-       if (self->ms.map->dso->annotate_warned)
-               return -1;
-
-       if (hist_entry__annotate(self, &head) < 0) {
-               ui__error_window(browser__last_msg);
-               return -1;
-       }
-
-       ui_helpline__push("Press <- or ESC to exit");
-
-       memset(&browser, 0, sizeof(browser));
-       browser.entries         = &head;
-       browser.refresh_entries = hist_entry__annotate_browser_refresh;
-       browser.seek            = ui_browser__list_head_seek;
-       browser.priv = self;
-       list_for_each_entry(pos, &head, node) {
-               size_t line_len = strlen(pos->line);
-               if (browser.width < line_len)
-                       browser.width = line_len;
-               ++browser.nr_entries;
-       }
-
-       browser.width += 18; /* Percentage */
-       ui_browser__show(&browser, self->ms.sym->name);
-       newtFormAddHotKey(browser.form, ' ');
-       ret = ui_browser__run(&browser, &es);
-       newtFormDestroy(browser.form);
-       newtPopWindow();
-       list_for_each_entry_safe(pos, n, &head, node) {
-               list_del(&pos->node);
-               objdump_line__free(pos);
-       }
-       ui_helpline__pop();
-       return ret;
-}
-
-struct hist_browser {
-       struct ui_browser   b;
-       struct hists        *hists;
-       struct hist_entry   *he_selection;
-       struct map_symbol   *selection;
-};
-
-static void hist_browser__reset(struct hist_browser *self);
-static int hist_browser__run(struct hist_browser *self, const char *title,
-                            struct newtExitStruct *es);
-static unsigned int hist_browser__refresh_entries(struct ui_browser *self);
-static void ui_browser__hists_seek(struct ui_browser *self,
-                                  off_t offset, int whence);
-
-static struct hist_browser *hist_browser__new(struct hists *hists)
-{
-       struct hist_browser *self = zalloc(sizeof(*self));
-
-       if (self) {
-               self->hists = hists;
-               self->b.refresh_entries = hist_browser__refresh_entries;
-               self->b.seek = ui_browser__hists_seek;
-       }
-
-       return self;
-}
-
-static void hist_browser__delete(struct hist_browser *self)
-{
-       newtFormDestroy(self->b.form);
-       newtPopWindow();
-       free(self);
-}
-
-static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self)
-{
-       return self->he_selection;
-}
-
-static struct thread *hist_browser__selected_thread(struct hist_browser *self)
-{
-       return self->he_selection->thread;
-}
-
-static int hist_browser__title(char *bf, size_t size, const char *ev_name,
-                              const struct dso *dso, const struct thread *thread)
-{
-       int printed = 0;
-
-       if (thread)
-               printed += snprintf(bf + printed, size - printed,
-                                   "Thread: %s(%d)",
-                                   (thread->comm_set ?  thread->comm : ""),
-                                   thread->pid);
-       if (dso)
-               printed += snprintf(bf + printed, size - printed,
-                                   "%sDSO: %s", thread ? " " : "",
-                                   dso->short_name);
-       return printed ?: snprintf(bf, size, "Event: %s", ev_name);
-}
-
-int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
-{
-       struct hist_browser *browser = hist_browser__new(self);
-       struct pstack *fstack;
-       const struct thread *thread_filter = NULL;
-       const struct dso *dso_filter = NULL;
-       struct newtExitStruct es;
-       char msg[160];
-       int key = -1;
-
-       if (browser == NULL)
-               return -1;
-
-       fstack = pstack__new(2);
-       if (fstack == NULL)
-               goto out;
-
-       ui_helpline__push(helpline);
-
-       hist_browser__title(msg, sizeof(msg), ev_name,
-                           dso_filter, thread_filter);
-
-       while (1) {
-               const struct thread *thread;
-               const struct dso *dso;
-               char *options[16];
-               int nr_options = 0, choice = 0, i,
-                   annotate = -2, zoom_dso = -2, zoom_thread = -2;
-
-               if (hist_browser__run(browser, msg, &es))
-                       break;
-
-               thread = hist_browser__selected_thread(browser);
-               dso = browser->selection->map ? browser->selection->map->dso : NULL;
-
-               if (es.reason == NEWT_EXIT_HOTKEY) {
-                       key = es.u.key;
-
-                       switch (key) {
-                       case NEWT_KEY_F1:
-                               goto do_help;
-                       case NEWT_KEY_TAB:
-                       case NEWT_KEY_UNTAB:
-                               /*
-                                * Exit the browser, let hists__browser_tree
-                                * go to the next or previous
-                                */
-                               goto out_free_stack;
-                       default:;
-                       }
-
-                       key = toupper(key);
-                       switch (key) {
-                       case 'A':
-                               if (browser->selection->map == NULL &&
-                                   browser->selection->map->dso->annotate_warned)
-                                       continue;
-                               goto do_annotate;
-                       case 'D':
-                               goto zoom_dso;
-                       case 'T':
-                               goto zoom_thread;
-                       case 'H':
-                       case '?':
-do_help:
-                               ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
-                                               "<-        Zoom out\n"
-                                               "a         Annotate current symbol\n"
-                                               "h/?/F1    Show this window\n"
-                                               "d         Zoom into current DSO\n"
-                                               "t         Zoom into current Thread\n"
-                                               "q/CTRL+C  Exit browser");
-                               continue;
-                       default:;
-                       }
-                       if (is_exit_key(key)) {
-                               if (key == NEWT_KEY_ESCAPE) {
-                                       if (dialog_yesno("Do you really want to exit?"))
-                                               break;
-                                       else
-                                               continue;
-                               } else
-                                       break;
-                       }
-
-                       if (es.u.key == NEWT_KEY_LEFT) {
-                               const void *top;
-
-                               if (pstack__empty(fstack))
-                                       continue;
-                               top = pstack__pop(fstack);
-                               if (top == &dso_filter)
-                                       goto zoom_out_dso;
-                               if (top == &thread_filter)
-                                       goto zoom_out_thread;
-                               continue;
-                       }
-               }
-
-               if (browser->selection->sym != NULL &&
-                   !browser->selection->map->dso->annotate_warned &&
-                   asprintf(&options[nr_options], "Annotate %s",
-                            browser->selection->sym->name) > 0)
-                       annotate = nr_options++;
-
-               if (thread != NULL &&
-                   asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
-                            (thread_filter ? "out of" : "into"),
-                            (thread->comm_set ? thread->comm : ""),
-                            thread->pid) > 0)
-                       zoom_thread = nr_options++;
-
-               if (dso != NULL &&
-                   asprintf(&options[nr_options], "Zoom %s %s DSO",
-                            (dso_filter ? "out of" : "into"),
-                            (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
-                       zoom_dso = nr_options++;
-
-               options[nr_options++] = (char *)"Exit";
-
-               choice = popup_menu(nr_options, options);
-
-               for (i = 0; i < nr_options - 1; ++i)
-                       free(options[i]);
-
-               if (choice == nr_options - 1)
-                       break;
-
-               if (choice == -1)
-                       continue;
-
-               if (choice == annotate) {
-                       struct hist_entry *he;
-do_annotate:
-                       if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
-                               browser->selection->map->dso->annotate_warned = 1;
-                               ui_helpline__puts("No vmlinux file found, can't "
-                                                "annotate with just a "
-                                                "kallsyms file");
-                               continue;
-                       }
-
-                       he = hist_browser__selected_entry(browser);
-                       if (he == NULL)
-                               continue;
-
-                       hist_entry__tui_annotate(he);
-               } else if (choice == zoom_dso) {
-zoom_dso:
-                       if (dso_filter) {
-                               pstack__remove(fstack, &dso_filter);
-zoom_out_dso:
-                               ui_helpline__pop();
-                               dso_filter = NULL;
-                       } else {
-                               if (dso == NULL)
-                                       continue;
-                               ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
-                                                  dso->kernel ? "the Kernel" : dso->short_name);
-                               dso_filter = dso;
-                               pstack__push(fstack, &dso_filter);
-                       }
-                       hists__filter_by_dso(self, dso_filter);
-                       hist_browser__title(msg, sizeof(msg), ev_name,
-                                           dso_filter, thread_filter);
-                       hist_browser__reset(browser);
-               } else if (choice == zoom_thread) {
-zoom_thread:
-                       if (thread_filter) {
-                               pstack__remove(fstack, &thread_filter);
-zoom_out_thread:
-                               ui_helpline__pop();
-                               thread_filter = NULL;
-                       } else {
-                               ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
-                                                  thread->comm_set ? thread->comm : "",
-                                                  thread->pid);
-                               thread_filter = thread;
-                               pstack__push(fstack, &thread_filter);
-                       }
-                       hists__filter_by_thread(self, thread_filter);
-                       hist_browser__title(msg, sizeof(msg), ev_name,
-                                           dso_filter, thread_filter);
-                       hist_browser__reset(browser);
-               }
-       }
-out_free_stack:
-       pstack__delete(fstack);
-out:
-       hist_browser__delete(browser);
-       return key;
-}
-
-int hists__tui_browse_tree(struct rb_root *self, const char *help)
-{
-       struct rb_node *first = rb_first(self), *nd = first, *next;
-       int key = 0;
-
-       while (nd) {
-               struct hists *hists = rb_entry(nd, struct hists, rb_node);
-               const char *ev_name = __event_name(hists->type, hists->config);
-
-               key = hists__browse(hists, help, ev_name);
-
-               if (is_exit_key(key))
-                       break;
-
-               switch (key) {
-               case NEWT_KEY_TAB:
-                       next = rb_next(nd);
-                       if (next)
-                               nd = next;
-                       break;
-               case NEWT_KEY_UNTAB:
-                       if (nd == first)
-                               continue;
-                       nd = rb_prev(nd);
-               default:
-                       break;
-               }
-       }
-
-       return key;
-}
-
-static struct newtPercentTreeColors {
-       const char *topColorFg, *topColorBg;
-       const char *mediumColorFg, *mediumColorBg;
-       const char *normalColorFg, *normalColorBg;
-       const char *selColorFg, *selColorBg;
-       const char *codeColorFg, *codeColorBg;
-} defaultPercentTreeColors = {
-       "red",       "lightgray",
-       "green",     "lightgray",
-       "black",     "lightgray",
-       "lightgray", "magenta",
-       "blue",      "lightgray",
-};
-
-static void newt_suspend(void *d __used)
-{
-       newtSuspend();
-       raise(SIGTSTP);
-       newtResume();
-}
-
-void setup_browser(void)
-{
-       struct newtPercentTreeColors *c = &defaultPercentTreeColors;
-
-       if (!isatty(1) || !use_browser || dump_trace) {
-               use_browser = 0;
-               setup_pager();
-               return;
-       }
-
-       use_browser = 1;
-       newtInit();
-       newtCls();
-       newtSetSuspendCallback(newt_suspend, NULL);
-       ui_helpline__puts(" ");
-       sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
-       sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
-       sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
-       sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
-       sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
-}
-
-void exit_browser(bool wait_for_ok)
-{
-       if (use_browser > 0) {
-               if (wait_for_ok) {
-                       char title[] = "Fatal Error", ok[] = "Ok";
-                       newtWinMessage(title, ok, browser__last_msg);
-               }
-               newtFinished();
-       }
-}
-
-static void hist_browser__refresh_dimensions(struct hist_browser *self)
-{
-       /* 3 == +/- toggle symbol before actual hist_entry rendering */
-       self->b.width = 3 + (hists__sort_list_width(self->hists) +
-                            sizeof("[k]"));
-}
-
-static void hist_browser__reset(struct hist_browser *self)
-{
-       self->b.nr_entries = self->hists->nr_entries;
-       hist_browser__refresh_dimensions(self);
-       ui_browser__reset_index(&self->b);
-}
-
-static char tree__folded_sign(bool unfolded)
-{
-       return unfolded ? '-' : '+';
-}
-
-static char map_symbol__folded(const struct map_symbol *self)
-{
-       return self->has_children ? tree__folded_sign(self->unfolded) : ' ';
-}
-
-static char hist_entry__folded(const struct hist_entry *self)
-{
-       return map_symbol__folded(&self->ms);
-}
-
-static char callchain_list__folded(const struct callchain_list *self)
-{
-       return map_symbol__folded(&self->ms);
-}
-
-static bool map_symbol__toggle_fold(struct map_symbol *self)
-{
-       if (!self->has_children)
-               return false;
-
-       self->unfolded = !self->unfolded;
-       return true;
-}
-
-#define LEVEL_OFFSET_STEP 3
-
-static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
-                                                    struct callchain_node *chain_node,
-                                                    u64 total, int level,
-                                                    unsigned short row,
-                                                    off_t *row_offset,
-                                                    bool *is_current_entry)
+static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
+                                                    struct callchain_node *chain_node,
+                                                    u64 total, int level,
+                                                    unsigned short row,
+                                                    off_t *row_offset,
+                                                    bool *is_current_entry)
 {
        struct rb_node *node;
        int first_row = row, width, offset = level * LEVEL_OFFSET_STEP;
@@ -1048,7 +342,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
                        }
 
                        SLsmg_set_color(color);
-                       SLsmg_gotorc(self->b.top + row, self->b.left);
+                       SLsmg_gotorc(self->b.y + row, self->b.x);
                        slsmg_write_nstring(" ", offset + extra_offset);
                        slsmg_printf("%c ", folded_sign);
                        slsmg_write_nstring(str, width);
@@ -1111,7 +405,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *self,
                }
 
                s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
-               SLsmg_gotorc(self->b.top + row, self->b.left);
+               SLsmg_gotorc(self->b.y + row, self->b.x);
                SLsmg_set_color(color);
                slsmg_write_nstring(" ", offset);
                slsmg_printf("%c ", folded_sign);
@@ -1191,7 +485,7 @@ static int hist_browser__show_entry(struct hist_browser *self,
                }
 
                SLsmg_set_color(color);
-               SLsmg_gotorc(self->b.top + row, self->b.left);
+               SLsmg_gotorc(self->b.y + row, self->b.x);
                if (symbol_conf.use_callchain) {
                        slsmg_printf("%c ", folded_sign);
                        width -= 2;
@@ -1213,16 +507,16 @@ static int hist_browser__show_entry(struct hist_browser *self,
        return printed;
 }
 
-static unsigned int hist_browser__refresh_entries(struct ui_browser *self)
+static unsigned int hist_browser__refresh(struct ui_browser *self)
 {
        unsigned row = 0;
        struct rb_node *nd;
        struct hist_browser *hb = container_of(self, struct hist_browser, b);
 
-       if (self->first_visible_entry == NULL)
-               self->first_visible_entry = rb_first(&hb->hists->entries);
+       if (self->top == NULL)
+               self->top = rb_first(&hb->hists->entries);
 
-       for (nd = self->first_visible_entry; nd; nd = rb_next(nd)) {
+       for (nd = self->top; nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 
                if (h->filtered)
@@ -1236,57 +530,6 @@ static unsigned int hist_browser__refresh_entries(struct ui_browser *self)
        return row;
 }
 
-static void callchain_node__init_have_children_rb_tree(struct callchain_node *self)
-{
-       struct rb_node *nd = rb_first(&self->rb_root);
-
-       for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
-               struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
-               struct callchain_list *chain;
-               int first = true;
-
-               list_for_each_entry(chain, &child->val, list) {
-                       if (first) {
-                               first = false;
-                               chain->ms.has_children = chain->list.next != &child->val ||
-                                                        rb_first(&child->rb_root) != NULL;
-                       } else
-                               chain->ms.has_children = chain->list.next == &child->val &&
-                                                        rb_first(&child->rb_root) != NULL;
-               }
-
-               callchain_node__init_have_children_rb_tree(child);
-       }
-}
-
-static void callchain_node__init_have_children(struct callchain_node *self)
-{
-       struct callchain_list *chain;
-
-       list_for_each_entry(chain, &self->val, list)
-               chain->ms.has_children = rb_first(&self->rb_root) != NULL;
-
-       callchain_node__init_have_children_rb_tree(self);
-}
-
-static void callchain__init_have_children(struct rb_root *self)
-{
-       struct rb_node *nd;
-
-       for (nd = rb_first(self); nd; nd = rb_next(nd)) {
-               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
-               callchain_node__init_have_children(node);
-       }
-}
-
-static void hist_entry__init_have_children(struct hist_entry *self)
-{
-       if (!self->init_have_children) {
-               callchain__init_have_children(&self->sorted_chain);
-               self->init_have_children = true;
-       }
-}
-
 static struct rb_node *hists__filter_entries(struct rb_node *nd)
 {
        while (nd != NULL) {
@@ -1325,7 +568,7 @@ static void ui_browser__hists_seek(struct ui_browser *self,
                nd = hists__filter_entries(rb_first(self->entries));
                break;
        case SEEK_CUR:
-               nd = self->first_visible_entry;
+               nd = self->top;
                goto do_offset;
        case SEEK_END:
                nd = hists__filter_prev_entries(rb_last(self->entries));
@@ -1339,7 +582,7 @@ static void ui_browser__hists_seek(struct ui_browser *self,
         * Moves not relative to the first visible entry invalidates its
         * row_offset:
         */
-       h = rb_entry(self->first_visible_entry, struct hist_entry, rb_node);
+       h = rb_entry(self->top, struct hist_entry, rb_node);
        h->row_offset = 0;
 
        /*
@@ -1367,7 +610,7 @@ do_offset:
                                } else {
                                        h->row_offset += offset;
                                        offset = 0;
-                                       self->first_visible_entry = nd;
+                                       self->top = nd;
                                        break;
                                }
                        }
@@ -1375,7 +618,7 @@ do_offset:
                        if (nd == NULL)
                                break;
                        --offset;
-                       self->first_visible_entry = nd;
+                       self->top = nd;
                } while (offset != 0);
        } else if (offset < 0) {
                while (1) {
@@ -1388,7 +631,7 @@ do_offset:
                                        } else {
                                                h->row_offset += offset;
                                                offset = 0;
-                                               self->first_visible_entry = nd;
+                                               self->top = nd;
                                                break;
                                        }
                                } else {
@@ -1398,7 +641,7 @@ do_offset:
                                        } else {
                                                h->row_offset = h->nr_rows + offset;
                                                offset = 0;
-                                               self->first_visible_entry = nd;
+                                               self->top = nd;
                                                break;
                                        }
                                }
@@ -1408,161 +651,298 @@ do_offset:
                        if (nd == NULL)
                                break;
                        ++offset;
-                       self->first_visible_entry = nd;
+                       self->top = nd;
                        if (offset == 0) {
                                /*
-                                * Last unfiltered hist_entry, check if it is
-                                * unfolded, if it is then we should have
-                                * row_offset at its last entry.
+                                * Last unfiltered hist_entry, check if it is
+                                * unfolded, if it is then we should have
+                                * row_offset at its last entry.
+                                */
+                               h = rb_entry(nd, struct hist_entry, rb_node);
+                               if (h->ms.unfolded)
+                                       h->row_offset = h->nr_rows;
+                               break;
+                       }
+                       first = false;
+               }
+       } else {
+               self->top = nd;
+               h = rb_entry(nd, struct hist_entry, rb_node);
+               h->row_offset = 0;
+       }
+}
+
+static struct hist_browser *hist_browser__new(struct hists *hists)
+{
+       struct hist_browser *self = zalloc(sizeof(*self));
+
+       if (self) {
+               self->hists = hists;
+               self->b.refresh = hist_browser__refresh;
+               self->b.seek = ui_browser__hists_seek;
+       }
+
+       return self;
+}
+
+static void hist_browser__delete(struct hist_browser *self)
+{
+       newtFormDestroy(self->b.form);
+       newtPopWindow();
+       free(self);
+}
+
+static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self)
+{
+       return self->he_selection;
+}
+
+static struct thread *hist_browser__selected_thread(struct hist_browser *self)
+{
+       return self->he_selection->thread;
+}
+
+static int hist_browser__title(char *bf, size_t size, const char *ev_name,
+                              const struct dso *dso, const struct thread *thread)
+{
+       int printed = 0;
+
+       if (thread)
+               printed += snprintf(bf + printed, size - printed,
+                                   "Thread: %s(%d)",
+                                   (thread->comm_set ?  thread->comm : ""),
+                                   thread->pid);
+       if (dso)
+               printed += snprintf(bf + printed, size - printed,
+                                   "%sDSO: %s", thread ? " " : "",
+                                   dso->short_name);
+       return printed ?: snprintf(bf, size, "Event: %s", ev_name);
+}
+
+int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
+{
+       struct hist_browser *browser = hist_browser__new(self);
+       struct pstack *fstack;
+       const struct thread *thread_filter = NULL;
+       const struct dso *dso_filter = NULL;
+       struct newtExitStruct es;
+       char msg[160];
+       int key = -1;
+
+       if (browser == NULL)
+               return -1;
+
+       fstack = pstack__new(2);
+       if (fstack == NULL)
+               goto out;
+
+       ui_helpline__push(helpline);
+
+       hist_browser__title(msg, sizeof(msg), ev_name,
+                           dso_filter, thread_filter);
+
+       while (1) {
+               const struct thread *thread;
+               const struct dso *dso;
+               char *options[16];
+               int nr_options = 0, choice = 0, i,
+                   annotate = -2, zoom_dso = -2, zoom_thread = -2,
+                   browse_map = -2;
+
+               if (hist_browser__run(browser, msg, &es))
+                       break;
+
+               thread = hist_browser__selected_thread(browser);
+               dso = browser->selection->map ? browser->selection->map->dso : NULL;
+
+               if (es.reason == NEWT_EXIT_HOTKEY) {
+                       key = es.u.key;
+
+                       switch (key) {
+                       case NEWT_KEY_F1:
+                               goto do_help;
+                       case NEWT_KEY_TAB:
+                       case NEWT_KEY_UNTAB:
+                               /*
+                                * Exit the browser, let hists__browser_tree
+                                * go to the next or previous
                                 */
-                               h = rb_entry(nd, struct hist_entry, rb_node);
-                               if (h->ms.unfolded)
-                                       h->row_offset = h->nr_rows;
-                               break;
+                               goto out_free_stack;
+                       default:;
                        }
-                       first = false;
-               }
-       } else {
-               self->first_visible_entry = nd;
-               h = rb_entry(nd, struct hist_entry, rb_node);
-               h->row_offset = 0;
-       }
-}
 
-static int callchain_node__count_rows_rb_tree(struct callchain_node *self)
-{
-       int n = 0;
-       struct rb_node *nd;
+                       switch (key) {
+                       case 'a':
+                               if (browser->selection->map == NULL &&
+                                   browser->selection->map->dso->annotate_warned)
+                                       continue;
+                               goto do_annotate;
+                       case 'd':
+                               goto zoom_dso;
+                       case 't':
+                               goto zoom_thread;
+                       case 'h':
+                       case '?':
+do_help:
+                               ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
+                                               "<-        Zoom out\n"
+                                               "a         Annotate current symbol\n"
+                                               "h/?/F1    Show this window\n"
+                                               "d         Zoom into current DSO\n"
+                                               "t         Zoom into current Thread\n"
+                                               "q/CTRL+C  Exit browser");
+                               continue;
+                       default:;
+                       }
+                       if (is_exit_key(key)) {
+                               if (key == NEWT_KEY_ESCAPE &&
+                                   !ui__dialog_yesno("Do you really want to exit?"))
+                                       continue;
+                               break;
+                       }
 
-       for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
-               struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
-               struct callchain_list *chain;
-               char folded_sign = ' '; /* No children */
+                       if (es.u.key == NEWT_KEY_LEFT) {
+                               const void *top;
 
-               list_for_each_entry(chain, &child->val, list) {
-                       ++n;
-                       /* We need this because we may not have children */
-                       folded_sign = callchain_list__folded(chain);
-                       if (folded_sign == '+')
-                               break;
+                               if (pstack__empty(fstack))
+                                       continue;
+                               top = pstack__pop(fstack);
+                               if (top == &dso_filter)
+                                       goto zoom_out_dso;
+                               if (top == &thread_filter)
+                                       goto zoom_out_thread;
+                               continue;
+                       }
                }
 
-               if (folded_sign == '-') /* Have children and they're unfolded */
-                       n += callchain_node__count_rows_rb_tree(child);
-       }
-
-       return n;
-}
+               if (browser->selection->sym != NULL &&
+                   !browser->selection->map->dso->annotate_warned &&
+                   asprintf(&options[nr_options], "Annotate %s",
+                            browser->selection->sym->name) > 0)
+                       annotate = nr_options++;
 
-static int callchain_node__count_rows(struct callchain_node *node)
-{
-       struct callchain_list *chain;
-       bool unfolded = false;
-       int n = 0;
+               if (thread != NULL &&
+                   asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
+                            (thread_filter ? "out of" : "into"),
+                            (thread->comm_set ? thread->comm : ""),
+                            thread->pid) > 0)
+                       zoom_thread = nr_options++;
 
-       list_for_each_entry(chain, &node->val, list) {
-               ++n;
-               unfolded = chain->ms.unfolded;
-       }
+               if (dso != NULL &&
+                   asprintf(&options[nr_options], "Zoom %s %s DSO",
+                            (dso_filter ? "out of" : "into"),
+                            (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
+                       zoom_dso = nr_options++;
 
-       if (unfolded)
-               n += callchain_node__count_rows_rb_tree(node);
+               if (browser->selection->map != NULL &&
+                   asprintf(&options[nr_options], "Browse map details") > 0)
+                       browse_map = nr_options++;
 
-       return n;
-}
+               options[nr_options++] = (char *)"Exit";
 
-static int callchain__count_rows(struct rb_root *chain)
-{
-       struct rb_node *nd;
-       int n = 0;
+               choice = ui__popup_menu(nr_options, options);
 
-       for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
-               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
-               n += callchain_node__count_rows(node);
-       }
+               for (i = 0; i < nr_options - 1; ++i)
+                       free(options[i]);
 
-       return n;
-}
+               if (choice == nr_options - 1)
+                       break;
 
-static bool hist_browser__toggle_fold(struct hist_browser *self)
-{
-       if (map_symbol__toggle_fold(self->selection)) {
-               struct hist_entry *he = self->he_selection;
+               if (choice == -1)
+                       continue;
 
-               hist_entry__init_have_children(he);
-               self->hists->nr_entries -= he->nr_rows;
+               if (choice == annotate) {
+                       struct hist_entry *he;
+do_annotate:
+                       if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
+                               browser->selection->map->dso->annotate_warned = 1;
+                               ui_helpline__puts("No vmlinux file found, can't "
+                                                "annotate with just a "
+                                                "kallsyms file");
+                               continue;
+                       }
 
-               if (he->ms.unfolded)
-                       he->nr_rows = callchain__count_rows(&he->sorted_chain);
-               else
-                       he->nr_rows = 0;
-               self->hists->nr_entries += he->nr_rows;
-               self->b.nr_entries = self->hists->nr_entries;
+                       he = hist_browser__selected_entry(browser);
+                       if (he == NULL)
+                               continue;
 
-               return true;
+                       hist_entry__tui_annotate(he);
+               } else if (choice == browse_map)
+                       map__browse(browser->selection->map);
+               else if (choice == zoom_dso) {
+zoom_dso:
+                       if (dso_filter) {
+                               pstack__remove(fstack, &dso_filter);
+zoom_out_dso:
+                               ui_helpline__pop();
+                               dso_filter = NULL;
+                       } else {
+                               if (dso == NULL)
+                                       continue;
+                               ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
+                                                  dso->kernel ? "the Kernel" : dso->short_name);
+                               dso_filter = dso;
+                               pstack__push(fstack, &dso_filter);
+                       }
+                       hists__filter_by_dso(self, dso_filter);
+                       hist_browser__title(msg, sizeof(msg), ev_name,
+                                           dso_filter, thread_filter);
+                       hist_browser__reset(browser);
+               } else if (choice == zoom_thread) {
+zoom_thread:
+                       if (thread_filter) {
+                               pstack__remove(fstack, &thread_filter);
+zoom_out_thread:
+                               ui_helpline__pop();
+                               thread_filter = NULL;
+                       } else {
+                               ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
+                                                  thread->comm_set ? thread->comm : "",
+                                                  thread->pid);
+                               thread_filter = thread;
+                               pstack__push(fstack, &thread_filter);
+                       }
+                       hists__filter_by_thread(self, thread_filter);
+                       hist_browser__title(msg, sizeof(msg), ev_name,
+                                           dso_filter, thread_filter);
+                       hist_browser__reset(browser);
+               }
        }
-
-       /* If it doesn't have children, no toggling performed */
-       return false;
+out_free_stack:
+       pstack__delete(fstack);
+out:
+       hist_browser__delete(browser);
+       return key;
 }
 
-static int hist_browser__run(struct hist_browser *self, const char *title,
-                            struct newtExitStruct *es)
+int hists__tui_browse_tree(struct rb_root *self, const char *help)
 {
-       char str[256], unit;
-       unsigned long nr_events = self->hists->stats.nr_events[PERF_RECORD_SAMPLE];
-
-       self->b.entries = &self->hists->entries;
-       self->b.nr_entries = self->hists->nr_entries;
-
-       hist_browser__refresh_dimensions(self);
-
-       nr_events = convert_unit(nr_events, &unit);
-       snprintf(str, sizeof(str), "Events: %lu%c                            ",
-                nr_events, unit);
-       newtDrawRootText(0, 0, str);
-
-       if (ui_browser__show(&self->b, title) < 0)
-               return -1;
+       struct rb_node *first = rb_first(self), *nd = first, *next;
+       int key = 0;
 
-       newtFormAddHotKey(self->b.form, 'A');
-       newtFormAddHotKey(self->b.form, 'a');
-       newtFormAddHotKey(self->b.form, '?');
-       newtFormAddHotKey(self->b.form, 'h');
-       newtFormAddHotKey(self->b.form, 'H');
-       newtFormAddHotKey(self->b.form, 'd');
+       while (nd) {
+               struct hists *hists = rb_entry(nd, struct hists, rb_node);
+               const char *ev_name = __event_name(hists->type, hists->config);
 
-       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT);
-       newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
+               key = hists__browse(hists, help, ev_name);
 
-       while (1) {
-               ui_browser__run(&self->b, es);
+               if (is_exit_key(key))
+                       break;
 
-               if (es->reason != NEWT_EXIT_HOTKEY)
+               switch (key) {
+               case NEWT_KEY_TAB:
+                       next = rb_next(nd);
+                       if (next)
+                               nd = next;
                        break;
-               switch (es->u.key) {
-               case 'd': { /* Debug */
-                       static int seq;
-                       struct hist_entry *h = rb_entry(self->b.first_visible_entry,
-                                                       struct hist_entry, rb_node);
-                       ui_helpline__pop();
-                       ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
-                                          seq++, self->b.nr_entries,
-                                          self->hists->nr_entries,
-                                          self->b.height,
-                                          self->b.index,
-                                          self->b.first_visible_entry_idx,
-                                          h->row_offset, h->nr_rows);
-               }
-                       continue;
-               case NEWT_KEY_ENTER:
-                       if (hist_browser__toggle_fold(self))
-                               break;
-                       /* fall thru */
+               case NEWT_KEY_UNTAB:
+                       if (nd == first)
+                               continue;
+                       nd = rb_prev(nd);
                default:
-                       return 0;
+                       break;
                }
        }
-       return 0;
+
+       return key;
 }
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
new file mode 100644 (file)
index 0000000..142b825
--- /dev/null
@@ -0,0 +1,161 @@
+#include "../libslang.h"
+#include <elf.h>
+#include <newt.h>
+#include <sys/ttydefaults.h>
+#include <ctype.h>
+#include <string.h>
+#include <linux/bitops.h>
+#include "../../debug.h"
+#include "../../symbol.h"
+#include "../browser.h"
+#include "../helpline.h"
+#include "map.h"
+
+static int ui_entry__read(const char *title, char *bf, size_t size, int width)
+{
+       struct newtExitStruct es;
+       newtComponent form, entry;
+       const char *result;
+       int err = -1;
+
+       newtCenteredWindow(width, 1, title);
+       form = newtForm(NULL, NULL, 0);
+       if (form == NULL)
+               return -1;
+
+       entry = newtEntry(0, 0, "0x", width, &result, NEWT_FLAG_SCROLL);
+       if (entry == NULL)
+               goto out_free_form;
+
+       newtFormAddComponent(form, entry);
+       newtFormAddHotKey(form, NEWT_KEY_ENTER);
+       newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
+       newtFormAddHotKey(form, NEWT_KEY_LEFT);
+       newtFormAddHotKey(form, CTRL('c'));
+       newtFormRun(form, &es);
+
+       if (result != NULL) {
+               strncpy(bf, result, size);
+               err = 0;
+       }
+out_free_form:
+       newtPopWindow();
+       newtFormDestroy(form);
+       return 0;
+}
+
+struct map_browser {
+       struct ui_browser b;
+       struct map        *map;
+       u16               namelen;
+       u8                addrlen;
+};
+
+static void map_browser__write(struct ui_browser *self, void *nd, int row)
+{
+       struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
+       struct map_browser *mb = container_of(self, struct map_browser, b);
+       bool current_entry = ui_browser__is_current_entry(self, row);
+       int color = ui_browser__percent_color(0, current_entry);
+
+       SLsmg_set_color(color);
+       slsmg_printf("%*llx %*llx %c ",
+                    mb->addrlen, sym->start, mb->addrlen, sym->end,
+                    sym->binding == STB_GLOBAL ? 'g' :
+                    sym->binding == STB_LOCAL  ? 'l' : 'w');
+       slsmg_write_nstring(sym->name, mb->namelen);
+}
+
+/* FIXME uber-kludgy, see comment on cmd_report... */
+static u32 *symbol__browser_index(struct symbol *self)
+{
+       return ((void *)self) - sizeof(struct rb_node) - sizeof(u32);
+}
+
+static int map_browser__search(struct map_browser *self)
+{
+       char target[512];
+       struct symbol *sym;
+       int err = ui_entry__read("Search by name/addr", target, sizeof(target), 40);
+
+       if (err)
+               return err;
+
+       if (target[0] == '0' && tolower(target[1]) == 'x') {
+               u64 addr = strtoull(target, NULL, 16);
+               sym = map__find_symbol(self->map, addr, NULL);
+       } else
+               sym = map__find_symbol_by_name(self->map, target, NULL);
+
+       if (sym != NULL) {
+               u32 *idx = symbol__browser_index(sym);
+
+               self->b.top = &sym->rb_node;
+               self->b.index = self->b.top_idx = *idx;
+       } else
+               ui_helpline__fpush("%s not found!", target);
+
+       return 0;
+}
+
+static int map_browser__run(struct map_browser *self, struct newtExitStruct *es)
+{
+       if (ui_browser__show(&self->b, self->map->dso->long_name,
+                            "Press <- or ESC to exit, %s / to search",
+                            verbose ? "" : "restart with -v to use") < 0)
+               return -1;
+
+       newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
+       newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
+       if (verbose)
+               newtFormAddHotKey(self->b.form, '/');
+
+       while (1) {
+               ui_browser__run(&self->b, es);
+
+               if (es->reason != NEWT_EXIT_HOTKEY)
+                       break;
+               if (verbose && es->u.key == '/')
+                       map_browser__search(self);
+               else
+                       break;
+       }
+
+       ui_browser__hide(&self->b);
+       return 0;
+}
+
+int map__browse(struct map *self)
+{
+       struct map_browser mb = {
+               .b = {
+                       .entries = &self->dso->symbols[self->type],
+                       .refresh = ui_browser__rb_tree_refresh,
+                       .seek    = ui_browser__rb_tree_seek,
+                       .write   = map_browser__write,
+               },
+               .map = self,
+       };
+       struct newtExitStruct es;
+       struct rb_node *nd;
+       char tmp[BITS_PER_LONG / 4];
+       u64 maxaddr = 0;
+
+       for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
+               struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
+
+               if (mb.namelen < pos->namelen)
+                       mb.namelen = pos->namelen;
+               if (maxaddr < pos->end)
+                       maxaddr = pos->end;
+               if (verbose) {
+                       u32 *idx = symbol__browser_index(pos);
+                       *idx = mb.b.nr_entries;
+               }
+               ++mb.b.nr_entries;
+       }
+
+       mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr);
+       mb.b.width += mb.addrlen * 2 + 4 + mb.namelen;
+       return map_browser__run(&mb, &es);
+}
diff --git a/tools/perf/util/ui/browsers/map.h b/tools/perf/util/ui/browsers/map.h
new file mode 100644 (file)
index 0000000..df8581a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PERF_UI_MAP_BROWSER_H_
+#define _PERF_UI_MAP_BROWSER_H_ 1
+struct map;
+
+int map__browse(struct map *self);
+#endif /* _PERF_UI_MAP_BROWSER_H_ */
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
new file mode 100644 (file)
index 0000000..8d79daa
--- /dev/null
@@ -0,0 +1,69 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <newt.h>
+
+#include "../debug.h"
+#include "helpline.h"
+
+void ui_helpline__pop(void)
+{
+       newtPopHelpLine();
+}
+
+void ui_helpline__push(const char *msg)
+{
+       newtPushHelpLine(msg);
+}
+
+void ui_helpline__vpush(const char *fmt, va_list ap)
+{
+       char *s;
+
+       if (vasprintf(&s, fmt, ap) < 0)
+               vfprintf(stderr, fmt, ap);
+       else {
+               ui_helpline__push(s);
+               free(s);
+       }
+}
+
+void ui_helpline__fpush(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       ui_helpline__vpush(fmt, ap);
+       va_end(ap);
+}
+
+void ui_helpline__puts(const char *msg)
+{
+       ui_helpline__pop();
+       ui_helpline__push(msg);
+}
+
+void ui_helpline__init(void)
+{
+       ui_helpline__puts(" ");
+}
+
+char ui_helpline__last_msg[1024];
+
+int ui_helpline__show_help(const char *format, va_list ap)
+{
+       int ret;
+       static int backlog;
+
+        ret = vsnprintf(ui_helpline__last_msg + backlog,
+                       sizeof(ui_helpline__last_msg) - backlog, format, ap);
+       backlog += ret;
+
+       if (ui_helpline__last_msg[backlog - 1] == '\n') {
+               ui_helpline__puts(ui_helpline__last_msg);
+               newtRefresh();
+               backlog = 0;
+       }
+
+       return ret;
+}
diff --git a/tools/perf/util/ui/helpline.h b/tools/perf/util/ui/helpline.h
new file mode 100644 (file)
index 0000000..ab6028d
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _PERF_UI_HELPLINE_H_
+#define _PERF_UI_HELPLINE_H_ 1
+
+void ui_helpline__init(void);
+void ui_helpline__pop(void);
+void ui_helpline__push(const char *msg);
+void ui_helpline__vpush(const char *fmt, va_list ap);
+void ui_helpline__fpush(const char *fmt, ...);
+void ui_helpline__puts(const char *msg);
+
+#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h
new file mode 100644 (file)
index 0000000..5623da8
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _PERF_UI_SLANG_H_
+#define _PERF_UI_SLANG_H_ 1
+/*
+ * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
+ * the build if it isn't defined. Use the equivalent one that glibc
+ * has on features.h.
+ */
+#include <features.h>
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
+#endif
+#include <slang.h>
+
+#if SLANG_VERSION < 20104
+#define slsmg_printf(msg, args...) \
+       SLsmg_printf((char *)msg, ##args)
+#define slsmg_write_nstring(msg, len) \
+       SLsmg_write_nstring((char *)msg, len)
+#define sltt_set_color(obj, name, fg, bg) \
+       SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
+#else
+#define slsmg_printf SLsmg_printf
+#define slsmg_write_nstring SLsmg_write_nstring
+#define sltt_set_color SLtt_set_color
+#endif
+
+#endif /* _PERF_UI_SLANG_H_ */
diff --git a/tools/perf/util/ui/progress.c b/tools/perf/util/ui/progress.c
new file mode 100644 (file)
index 0000000..d7fc399
--- /dev/null
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <newt.h>
+#include "../cache.h"
+#include "progress.h"
+
+struct ui_progress {
+       newtComponent form, scale;
+};
+
+struct ui_progress *ui_progress__new(const char *title, u64 total)
+{
+       struct ui_progress *self = malloc(sizeof(*self));
+
+       if (self != NULL) {
+               int cols;
+
+               if (use_browser <= 0)
+                       return self;
+               newtGetScreenSize(&cols, NULL);
+               cols -= 4;
+               newtCenteredWindow(cols, 1, title);
+               self->form  = newtForm(NULL, NULL, 0);
+               if (self->form == NULL)
+                       goto out_free_self;
+               self->scale = newtScale(0, 0, cols, total);
+               if (self->scale == NULL)
+                       goto out_free_form;
+               newtFormAddComponent(self->form, self->scale);
+               newtRefresh();
+       }
+
+       return self;
+
+out_free_form:
+       newtFormDestroy(self->form);
+out_free_self:
+       free(self);
+       return NULL;
+}
+
+void ui_progress__update(struct ui_progress *self, u64 curr)
+{
+       /*
+        * FIXME: We should have a per UI backend way of showing progress,
+        * stdio will just show a percentage as NN%, etc.
+        */
+       if (use_browser <= 0)
+               return;
+       newtScaleSet(self->scale, curr);
+       newtRefresh();
+}
+
+void ui_progress__delete(struct ui_progress *self)
+{
+       if (use_browser > 0) {
+               newtFormDestroy(self->form);
+               newtPopWindow();
+       }
+       free(self);
+}
diff --git a/tools/perf/util/ui/progress.h b/tools/perf/util/ui/progress.h
new file mode 100644 (file)
index 0000000..a3820a0
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _PERF_UI_PROGRESS_H_
+#define _PERF_UI_PROGRESS_H_ 1
+
+struct ui_progress;
+
+struct ui_progress *ui_progress__new(const char *title, u64 total);
+void ui_progress__delete(struct ui_progress *self);
+
+void ui_progress__update(struct ui_progress *self, u64 curr);
+
+#endif
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c
new file mode 100644 (file)
index 0000000..6620850
--- /dev/null
@@ -0,0 +1,42 @@
+#include <newt.h>
+#include <signal.h>
+#include <stdbool.h>
+
+#include "../cache.h"
+#include "../debug.h"
+#include "browser.h"
+#include "helpline.h"
+
+static void newt_suspend(void *d __used)
+{
+       newtSuspend();
+       raise(SIGTSTP);
+       newtResume();
+}
+
+void setup_browser(void)
+{
+       if (!isatty(1) || !use_browser || dump_trace) {
+               use_browser = 0;
+               setup_pager();
+               return;
+       }
+
+       use_browser = 1;
+       newtInit();
+       newtCls();
+       newtSetSuspendCallback(newt_suspend, NULL);
+       ui_helpline__init();
+       ui_browser__init();
+}
+
+void exit_browser(bool wait_for_ok)
+{
+       if (use_browser > 0) {
+               if (wait_for_ok) {
+                       char title[] = "Fatal Error", ok[] = "Ok";
+                       newtWinMessage(title, ok, ui_helpline__last_msg);
+               }
+               newtFinished();
+       }
+}
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
new file mode 100644 (file)
index 0000000..04600e2
--- /dev/null
@@ -0,0 +1,114 @@
+#include <newt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ttydefaults.h>
+
+#include "../cache.h"
+#include "../debug.h"
+#include "browser.h"
+#include "helpline.h"
+#include "util.h"
+
+newtComponent newt_form__new(void);
+
+static void newt_form__set_exit_keys(newtComponent self)
+{
+       newtFormAddHotKey(self, NEWT_KEY_LEFT);
+       newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
+       newtFormAddHotKey(self, 'Q');
+       newtFormAddHotKey(self, 'q');
+       newtFormAddHotKey(self, CTRL('c'));
+}
+
+newtComponent newt_form__new(void)
+{
+       newtComponent self = newtForm(NULL, NULL, 0);
+       if (self)
+               newt_form__set_exit_keys(self);
+       return self;
+}
+
+int ui__popup_menu(int argc, char * const argv[])
+{
+       struct newtExitStruct es;
+       int i, rc = -1, max_len = 5;
+       newtComponent listbox, form = newt_form__new();
+
+       if (form == NULL)
+               return -1;
+
+       listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT);
+       if (listbox == NULL)
+               goto out_destroy_form;
+
+       newtFormAddComponent(form, listbox);
+
+       for (i = 0; i < argc; ++i) {
+               int len = strlen(argv[i]);
+               if (len > max_len)
+                       max_len = len;
+               if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i))
+                       goto out_destroy_form;
+       }
+
+       newtCenteredWindow(max_len, argc, NULL);
+       newtFormRun(form, &es);
+       rc = newtListboxGetCurrent(listbox) - NULL;
+       if (es.reason == NEWT_EXIT_HOTKEY)
+               rc = -1;
+       newtPopWindow();
+out_destroy_form:
+       newtFormDestroy(form);
+       return rc;
+}
+
+int ui__help_window(const char *text)
+{
+       struct newtExitStruct es;
+       newtComponent tb, form = newt_form__new();
+       int rc = -1;
+       int max_len = 0, nr_lines = 0;
+       const char *t;
+
+       if (form == NULL)
+               return -1;
+
+       t = text;
+       while (1) {
+               const char *sep = strchr(t, '\n');
+               int len;
+
+               if (sep == NULL)
+                       sep = strchr(t, '\0');
+               len = sep - t;
+               if (max_len < len)
+                       max_len = len;
+               ++nr_lines;
+               if (*sep == '\0')
+                       break;
+               t = sep + 1;
+       }
+
+       tb = newtTextbox(0, 0, max_len, nr_lines, 0);
+       if (tb == NULL)
+               goto out_destroy_form;
+
+       newtTextboxSetText(tb, text);
+       newtFormAddComponent(form, tb);
+       newtCenteredWindow(max_len, nr_lines, NULL);
+       newtFormRun(form, &es);
+       newtPopWindow();
+       rc = 0;
+out_destroy_form:
+       newtFormDestroy(form);
+       return rc;
+}
+
+bool ui__dialog_yesno(const char *msg)
+{
+       /* newtWinChoice should really be accepting const char pointers... */
+       char yes[] = "Yes", no[] = "No";
+       return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
+}
diff --git a/tools/perf/util/ui/util.h b/tools/perf/util/ui/util.h
new file mode 100644 (file)
index 0000000..afcbc1d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _PERF_UI_UTIL_H_
+#define _PERF_UI_UTIL_H_ 1
+
+#include <stdbool.h>
+
+int ui__popup_menu(int argc, char * const argv[]);
+int ui__help_window(const char *text);
+bool ui__dialog_yesno(const char *msg);
+
+#endif /* _PERF_UI_UTIL_H_ */