Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 13:04:38 +0000 (09:04 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 13:04:38 +0000 (09:04 -0400)
Merge third patchbomb from Andrew Morton:

 - various misc things

 - a couple of lib/ optimisations

 - provide DIV_ROUND_CLOSEST_ULL()

 - checkpatch updates

 - rtc tree

 - befs, nilfs2, hfs, hfsplus, fatfs, adfs, affs, bfs

 - ptrace fixes

 - fork() fixes

 - seccomp cleanups

 - more mmap_sem hold time reductions from Davidlohr

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (138 commits)
  proc: show locks in /proc/pid/fdinfo/X
  docs: add missing and new /proc/PID/status file entries, fix typos
  drivers/rtc/rtc-at91rm9200.c: make IO endian agnostic
  Documentation/spi/spidev_test.c: fix warning
  drivers/rtc/rtc-s5m.c: allow usage on device type different than main MFD type
  .gitignore: ignore *.tar
  MAINTAINERS: add Mediatek SoC mailing list
  tomoyo: reduce mmap_sem hold for mm->exe_file
  powerpc/oprofile: reduce mmap_sem hold for exe_file
  oprofile: reduce mmap_sem hold for mm->exe_file
  mips: ip32: add platform data hooks to use DS1685 driver
  lib/Kconfig: fix up HAVE_ARCH_BITREVERSE help text
  x86: switch to using asm-generic for seccomp.h
  sparc: switch to using asm-generic for seccomp.h
  powerpc: switch to using asm-generic for seccomp.h
  parisc: switch to using asm-generic for seccomp.h
  mips: switch to using asm-generic for seccomp.h
  microblaze: use asm-generic for seccomp.h
  arm: use asm-generic for seccomp.h
  seccomp: allow COMPAT sigreturn overrides
  ...

158 files changed:
.gitignore
Documentation/CodingStyle
Documentation/SubmittingPatches
Documentation/devicetree/bindings/rtc/digicolor-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt
Documentation/filesystems/proc.txt
Documentation/spi/spidev_test.c
Documentation/sysctl/kernel.txt
MAINTAINERS
arch/alpha/include/asm/processor.h
arch/arc/kernel/troubleshoot.c
arch/arm/include/asm/Kbuild
arch/arm/include/asm/seccomp.h [deleted file]
arch/microblaze/include/asm/seccomp.h
arch/mips/configs/ip32_defconfig
arch/mips/include/asm/mach-ip32/mc146818rtc.h [deleted file]
arch/mips/include/asm/seccomp.h
arch/mips/sgi-ip32/ip32-platform.c
arch/mips/sgi-ip32/ip32-reset.c
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/seccomp.h [deleted file]
arch/powerpc/include/asm/seccomp.h [new file with mode: 0644]
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/seccomp.h [deleted file]
arch/powerpc/oprofile/cell/spu_task_sync.c
arch/sparc/include/asm/seccomp.h
arch/x86/include/asm/seccomp.h
arch/x86/include/asm/seccomp_32.h [deleted file]
arch/x86/include/asm/seccomp_64.h [deleted file]
drivers/clk/bcm/clk-kona.c
drivers/clk/bcm/clk-kona.h
drivers/cpuidle/governors/menu.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c
drivers/hwmon/ina2xx.c
drivers/hwmon/lm85.c
drivers/hwmon/w83795.c
drivers/media/dvb-frontends/cxd2820r_c.c
drivers/media/dvb-frontends/cxd2820r_core.c
drivers/media/dvb-frontends/cxd2820r_priv.h
drivers/media/dvb-frontends/cxd2820r_t.c
drivers/media/dvb-frontends/cxd2820r_t2.c
drivers/memstick/core/mspro_block.c
drivers/oprofile/buffer_sync.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/hctosys.c
drivers/rtc/interface.c
drivers/rtc/rtc-ab-b5ze-s3.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-da9052.c
drivers/rtc/rtc-digicolor.c [new file with mode: 0644]
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1685.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-efi-platform.c
drivers/rtc/rtc-em3027.c
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max8997.c
drivers/rtc/rtc-msm6242.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-opal.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-twl.c
drivers/rtc/rtc-x1205.c
drivers/scsi/bfa/bfad.c
firmware/ihex2fw.c
fs/adfs/dir_fplus.c
fs/adfs/super.c
fs/affs/affs.h
fs/affs/amigaffs.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/namei.c
fs/affs/super.c
fs/befs/befs.h
fs/befs/datastream.c
fs/befs/io.c
fs/befs/linuxvfs.c
fs/befs/super.c
fs/bfs/dir.c
fs/binfmt_misc.c
fs/exec.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/fat.h
fs/fat/fatent.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/file.c
fs/hfs/dir.c
fs/hfsplus/bfind.c
fs/hfsplus/catalog.c
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/hfsplus/ioctl.c
fs/hfsplus/xattr.c
fs/hfsplus/xattr.h
fs/hfsplus/xattr_security.c
fs/hfsplus/xattr_trusted.c
fs/hfsplus/xattr_user.c
fs/locks.c
fs/nilfs2/alloc.c
fs/nilfs2/bmap.c
fs/nilfs2/bmap.h
fs/nilfs2/btree.c
fs/nilfs2/cpfile.c
fs/nilfs2/direct.c
fs/nilfs2/inode.c
fs/nilfs2/mdt.c
fs/nilfs2/mdt.h
fs/nilfs2/page.c
fs/nilfs2/segment.c
fs/nilfs2/super.c
fs/proc/fd.c
include/asm-generic/seccomp.h
include/linux/bitmap.h
include/linux/bitops.h
include/linux/fs.h
include/linux/kconfig.h
include/linux/kernel.h
include/linux/mfd/samsung/rtc.h
include/linux/mm_types.h
include/linux/sysctl.h
include/linux/util_macros.h [new file with mode: 0644]
include/uapi/asm-generic/errno.h
init/main.c
kernel/fork.c
kernel/gcov/base.c
kernel/pid.c
kernel/ptrace.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
lib/Kconfig
lib/Makefile
lib/bitmap.c
lib/cpumask.c
lib/dma-debug.c
lib/find_bit.c [new file with mode: 0644]
lib/find_last_bit.c
lib/find_next_bit.c [deleted file]
lib/vsprintf.c
scripts/Makefile.kasan
scripts/checkpatch.pl
scripts/spelling.txt
security/tomoyo/util.c
sound/soc/codecs/pcm512x.c

index acb6afe..4ad4a98 100644 (file)
@@ -24,6 +24,7 @@
 *.order
 *.elf
 *.bin
+*.tar
 *.gz
 *.bz2
 *.lzma
index 449a8a1..4d4f06d 100644 (file)
@@ -659,6 +659,19 @@ macros using parameters.
 #define CONSTANT 0x4000
 #define CONSTEXP (CONSTANT | 3)
 
+5) namespace collisions when defining local variables in macros resembling
+functions:
+
+#define FOO(x)                         \
+({                                     \
+       typeof(x) ret;                  \
+       ret = calc_ret(x);              \
+       (ret);                          \
+)}
+
+ret is a common name for a local variable - __foo_ret is less likely
+to collide with an existing variable.
+
 The cpp manual deals with macros exhaustively. The gcc internals manual also
 covers RTL which is used frequently with assembly language in the kernel.
 
index 447671b..b03a832 100644 (file)
@@ -614,8 +614,8 @@ The canonical patch message body contains the following:
 
   - An empty line.
 
-  - The body of the explanation, which will be copied to the
-    permanent changelog to describe this patch.
+  - The body of the explanation, line wrapped at 75 columns, which will
+    be copied to the permanent changelog to describe this patch.
 
   - The "Signed-off-by:" lines, described above, which will
     also go in the changelog.
diff --git a/Documentation/devicetree/bindings/rtc/digicolor-rtc.txt b/Documentation/devicetree/bindings/rtc/digicolor-rtc.txt
new file mode 100644 (file)
index 0000000..d464986
--- /dev/null
@@ -0,0 +1,17 @@
+Conexant Digicolor Real Time Clock controller
+
+This binding currently supports the CX92755 SoC.
+
+Required properties:
+- compatible: should be "cnxt,cx92755-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: rtc alarm interrupt
+
+Example:
+
+       rtc@f0000c30 {
+               compatible = "cnxt,cx92755-rtc";
+               reg = <0xf0000c30 0x18>;
+               interrupts = <25>;
+       };
index b800070..fa6a942 100644 (file)
@@ -7,6 +7,11 @@ Required properties:
   region.
 - interrupts: rtc alarm interrupt
 
+Optional properties:
+- stmp,crystal-freq: override crystal frequency as determined from fuse bits.
+  Only <32000> and <32768> are possible for the hardware.  Use <0> for
+  "no crystal".
+
 Example:
 
 rtc@80056000 {
index a07ba61..8e36c7e 100644 (file)
@@ -200,12 +200,12 @@ contains details information about the process itself.  Its fields are
 explained in Table 1-4.
 
 (for SMP CONFIG users)
-For making accounting scalable, RSS related information are handled in
-asynchronous manner and the vaule may not be very precise. To see a precise
+For making accounting scalable, RSS related information are handled in an
+asynchronous manner and the value may not be very precise. To see a precise
 snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
 It's slow but very precise.
 
-Table 1-2: Contents of the status files (as of 2.6.30-rc7)
+Table 1-2: Contents of the status files (as of 3.20.0)
 ..............................................................................
  Field                       Content
  Name                        filename of the executable
@@ -213,6 +213,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
                              in an uninterruptible wait, Z is zombie,
                             T is traced or stopped)
  Tgid                        thread group ID
+ Ngid                        NUMA group ID (0 if none)
  Pid                         process id
  PPid                        process id of the parent process
  TracerPid                   PID of process tracing this process (0 if not)
@@ -220,6 +221,10 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
  Gid                         Real, effective, saved set, and  file system GIDs
  FDSize                      number of file descriptor slots currently allocated
  Groups                      supplementary group list
+ NStgid                      descendant namespace thread group ID hierarchy
+ NSpid                       descendant namespace process ID hierarchy
+ NSpgid                      descendant namespace process group ID hierarchy
+ NSsid                       descendant namespace session ID hierarchy
  VmPeak                      peak virtual memory size
  VmSize                      total program size
  VmLck                       locked memory size
@@ -1704,6 +1709,10 @@ A typical output is
        flags:  0100002
        mnt_id: 19
 
+All locks associated with a file descriptor are shown in its fdinfo too.
+
+lock:       1: FLOCK  ADVISORY  WRITE 359 00:13:11691 0 EOF
+
 The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
 pair provide additional information particular to the objects they represent.
 
index 94f574b..135b3f5 100644 (file)
@@ -80,7 +80,7 @@ static void hex_dump(const void *src, size_t length, size_t line_size, char *pre
  *  Unescape - process hexadecimal escape character
  *      converts shell input "\x23" -> 0x23
  */
-int unespcape(char *_dst, char *_src, size_t len)
+static int unescape(char *_dst, char *_src, size_t len)
 {
        int ret = 0;
        char *src = _src;
@@ -304,7 +304,7 @@ int main(int argc, char *argv[])
                size = strlen(input_tx+1);
                tx = malloc(size);
                rx = malloc(size);
-               size = unespcape((char *)tx, input_tx, size);
+               size = unescape((char *)tx, input_tx, size);
                transfer(fd, tx, rx, size);
                free(rx);
                free(tx);
index 99d7eb3..c831001 100644 (file)
@@ -872,6 +872,27 @@ can be ORed together:
 
 ==============================================================
 
+threads-max
+
+This value controls the maximum number of threads that can be created
+using fork().
+
+During initialization the kernel sets this value such that even if the
+maximum number of threads is created, the thread structures occupy only
+a part (1/8th) of the available RAM pages.
+
+The minimum value that can be written to threads-max is 20.
+The maximum value that can be written to threads-max is given by the
+constant FUTEX_TID_MASK (0x3fffffff).
+If a value outside of this range is written to threads-max an error
+EINVAL occurs.
+
+The value written is checked against the available RAM pages. If the
+thread structures would occupy too much (more than 1/8th) of the
+available RAM pages threads-max is reduced accordingly.
+
+==============================================================
+
 unknown_nmi_panic:
 
 The value in this file affects behavior of handling NMI. When the
index bf990f5..f7bbaec 100644 (file)
@@ -1215,6 +1215,7 @@ F:        arch/arm/mach-orion5x/ts78xx-*
 ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/boot/dts/mt6*
 F:     arch/arm/boot/dts/mt8*
@@ -8183,6 +8184,7 @@ X:        kernel/torture.c
 
 REAL TIME CLOCK (RTC) SUBSYSTEM
 M:     Alessandro Zummo <a.zummo@towertech.it>
+M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
 L:     rtc-linux@googlegroups.com
 Q:     http://patchwork.ozlabs.org/project/rtc-linux/list/
 S:     Maintained
index b4cf036..43a7559 100644 (file)
@@ -44,6 +44,7 @@ struct task_struct;
 extern unsigned long thread_saved_pc(struct task_struct *);
 
 /* Do necessary setup to start up a newly executed thread.  */
+struct pt_regs;
 extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 
 /* Free all resources held by a thread. */
index 1badf9b..e00a018 100644 (file)
@@ -52,7 +52,7 @@ static void show_callee_regs(struct callee_regs *cregs)
        print_reg_file(&(cregs->r13), 13);
 }
 
-void print_task_path_n_nm(struct task_struct *tsk, char *buf)
+static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
 {
        struct path path;
        char *path_nm = NULL;
@@ -77,7 +77,6 @@ void print_task_path_n_nm(struct task_struct *tsk, char *buf)
 done:
        pr_info("Path: %s\n", path_nm);
 }
-EXPORT_SYMBOL(print_task_path_n_nm);
 
 static void show_faulting_vma(unsigned long address, char *buf)
 {
index eb0f43f..3c4596d 100644 (file)
@@ -21,6 +21,7 @@ generic-y += preempt.h
 generic-y += resource.h
 generic-y += rwsem.h
 generic-y += scatterlist.h
+generic-y += seccomp.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += sembuf.h
diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h
deleted file mode 100644 (file)
index 52b156b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_ARM_SECCOMP_H
-#define _ASM_ARM_SECCOMP_H
-
-#include <linux/unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#endif /* _ASM_ARM_SECCOMP_H */
index 0d91275..204618a 100644 (file)
@@ -3,14 +3,8 @@
 
 #include <linux/unistd.h>
 
-#define __NR_seccomp_read              __NR_read
-#define __NR_seccomp_write             __NR_write
-#define __NR_seccomp_exit              __NR_exit
 #define __NR_seccomp_sigreturn         __NR_sigreturn
 
-#define __NR_seccomp_read_32           __NR_read
-#define __NR_seccomp_write_32          __NR_write
-#define __NR_seccomp_exit_32           __NR_exit
-#define __NR_seccomp_sigreturn_32      __NR_sigreturn
+#include <asm-generic/seccomp.h>
 
 #endif /* _ASM_MICROBLAZE_SECCOMP_H */
index 70ffe9b..fe48220 100644 (file)
@@ -105,7 +105,8 @@ CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
 # CONFIG_RTC_INTF_SYSFS is not set
 # CONFIG_RTC_INTF_PROC is not set
-CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1685_FAMILY=y
+CONFIG_RTC_DRV_DS1685=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/mips/include/asm/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h
deleted file mode 100644 (file)
index 6b6bab4..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998, 2001, 03 by Ralf Baechle
- * Copyright (C) 2000 Harald Koerfgen
- *
- * RTC routines for IP32 style attached Dallas chip.
- */
-#ifndef __ASM_MACH_IP32_MC146818RTC_H
-#define __ASM_MACH_IP32_MC146818RTC_H
-
-#include <asm/ip32/mace.h>
-
-#define RTC_PORT(x)    (0x70 + (x))
-
-static unsigned char CMOS_READ(unsigned long addr)
-{
-       return mace->isa.rtc[addr << 8];
-}
-
-static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
-{
-       mace->isa.rtc[addr << 8] = data;
-}
-
-/*
- * FIXME: Do it right. For now just assume that no one lives in 20th century
- * and no O2 user in 22th century ;-)
- */
-#define mc146818_decode_year(year) ((year) + 2000)
-
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ASM_MACH_IP32_MC146818RTC_H */
index f29c75c..1d8a2e2 100644 (file)
@@ -2,11 +2,6 @@
 
 #include <linux/unistd.h>
 
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
 /*
  * Kludge alert:
  *
@@ -29,4 +24,6 @@
 
 #endif /* CONFIG_MIPS32_O32 */
 
+#include <asm-generic/seccomp.h>
+
 #endif /* __ASM_SECCOMP_H */
index 511e9ff..b522477 100644 (file)
@@ -9,10 +9,13 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/rtc/ds1685.h>
 
 #include <asm/ip32/mace.h>
 #include <asm/ip32/ip32_ints.h>
 
+extern void ip32_prepare_poweroff(void);
+
 #define MACEISA_SERIAL1_OFFS   offsetof(struct sgi_mace, isa.serial1)
 #define MACEISA_SERIAL2_OFFS   offsetof(struct sgi_mace, isa.serial2)
 
@@ -90,18 +93,47 @@ static __init int sgio2btns_devinit(void)
 
 device_initcall(sgio2btns_devinit);
 
-static struct resource sgio2_cmos_rsrc[] = {
+#define MACE_RTC_RES_START (MACE_BASE + offsetof(struct sgi_mace, isa.rtc))
+#define MACE_RTC_RES_END (MACE_RTC_RES_START + 32767)
+
+static struct resource ip32_rtc_resources[] = {
        {
-               .start = 0x70,
-               .end   = 0x71,
-               .flags = IORESOURCE_IO
+               .start  = MACEISA_RTC_IRQ,
+               .end    = MACEISA_RTC_IRQ,
+               .flags  = IORESOURCE_IRQ
+       }, {
+               .start  = MACE_RTC_RES_START,
+               .end    = MACE_RTC_RES_END,
+               .flags  = IORESOURCE_MEM,
        }
 };
 
-static __init int sgio2_cmos_devinit(void)
+/* RTC registers on IP32 are each padded by 256 bytes (0x100). */
+static struct ds1685_rtc_platform_data
+ip32_rtc_platform_data[] = {
+       {
+               .regstep = 0x100,
+               .bcd_mode = true,
+               .no_irq = false,
+               .uie_unsupported = false,
+               .alloc_io_resources = true,
+               .plat_prepare_poweroff = ip32_prepare_poweroff,
+       },
+};
+
+struct platform_device ip32_rtc_device = {
+       .name                   = "rtc-ds1685",
+       .id                     = -1,
+       .dev                    = {
+               .platform_data  = ip32_rtc_platform_data,
+       },
+       .num_resources          = ARRAY_SIZE(ip32_rtc_resources),
+       .resource               = ip32_rtc_resources,
+};
+
++static int __init sgio2_rtc_devinit(void)
 {
-       return IS_ERR(platform_device_register_simple("rtc_cmos", -1,
-                                                     sgio2_cmos_rsrc, 1));
+       return platform_device_register(&ip32_rtc_device);
 }
 
 device_initcall(sgio2_cmos_devinit);
index 44b3470..8bd415c 100644 (file)
 #include <linux/compiler.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
 #include <linux/delay.h>
-#include <linux/ds17287rtc.h>
+#include <linux/rtc/ds1685.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 
 #define POWERDOWN_FREQ         (HZ / 4)
 #define PANIC_FREQ             (HZ / 8)
 
-static struct timer_list power_timer, blink_timer, debounce_timer;
-static int has_panicked, shuting_down;
+extern struct platform_device ip32_rtc_device;
 
-static void ip32_machine_restart(char *command) __noreturn;
-static void ip32_machine_halt(void) __noreturn;
-static void ip32_machine_power_off(void) __noreturn;
+static struct timer_list power_timer, blink_timer;
+static int has_panicked, shutting_down;
 
-static void ip32_machine_restart(char *cmd)
+static __noreturn void ip32_poweroff(void *data)
 {
-       crime->control = CRIME_CONTROL_HARD_RESET;
-       while (1);
-}
+       void (*poweroff_func)(struct platform_device *) =
+               symbol_get(ds1685_rtc_poweroff);
+
+#ifdef CONFIG_MODULES
+       /* If the first __symbol_get failed, our module wasn't loaded. */
+       if (!poweroff_func) {
+               request_module("rtc-ds1685");
+               poweroff_func = symbol_get(ds1685_rtc_poweroff);
+       }
+#endif
 
-static inline void ip32_machine_halt(void)
-{
-       ip32_machine_power_off();
-}
+       if (!poweroff_func)
+               pr_emerg("RTC not available for power-off.  Spinning forever ...\n");
+       else {
+               (*poweroff_func)((struct platform_device *)data);
+               symbol_put(ds1685_rtc_poweroff);
+       }
 
-static void ip32_machine_power_off(void)
-{
-       unsigned char reg_a, xctrl_a, xctrl_b;
-
-       disable_irq(MACEISA_RTC_IRQ);
-       reg_a = CMOS_READ(RTC_REG_A);
-
-       /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */
-       reg_a &= ~DS_REGA_DV2;
-       reg_a |= DS_REGA_DV1;
-
-       CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
-       wbflush();
-       xctrl_b = CMOS_READ(DS_B1_XCTRL4B)
-                  | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE;
-       CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B);
-       xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS;
-       CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A);
-       wbflush();
-       /* adios amigos... */
-       CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A);
-       CMOS_WRITE(reg_a, RTC_REG_A);
-       wbflush();
-       while (1);
+       unreachable();
 }
 
-static void power_timeout(unsigned long data)
+static void ip32_machine_restart(char *cmd) __noreturn;
+static void ip32_machine_restart(char *cmd)
 {
-       ip32_machine_power_off();
+       msleep(20);
+       crime->control = CRIME_CONTROL_HARD_RESET;
+       unreachable();
 }
 
 static void blink_timeout(unsigned long data)
@@ -89,44 +77,27 @@ static void blink_timeout(unsigned long data)
        mod_timer(&blink_timer, jiffies + data);
 }
 
-static void debounce(unsigned long data)
+static void ip32_machine_halt(void)
 {
-       unsigned char reg_a, reg_c, xctrl_a;
-
-       reg_c = CMOS_READ(RTC_INTR_FLAGS);
-       reg_a = CMOS_READ(RTC_REG_A);
-       CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
-       wbflush();
-       xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
-       if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) {
-               /* Interrupt still being sent. */
-               debounce_timer.expires = jiffies + 50;
-               add_timer(&debounce_timer);
-
-               /* clear interrupt source */
-               CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
-               CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
-               return;
-       }
-       CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
-
-       if (has_panicked)
-               ip32_machine_restart(NULL);
+       ip32_poweroff(&ip32_rtc_device);
+}
 
-       enable_irq(MACEISA_RTC_IRQ);
+static void power_timeout(unsigned long data)
+{
+       ip32_poweroff(&ip32_rtc_device);
 }
 
-static inline void ip32_power_button(void)
+void ip32_prepare_poweroff(void)
 {
        if (has_panicked)
                return;
 
-       if (shuting_down || kill_cad_pid(SIGINT, 1)) {
+       if (shutting_down || kill_cad_pid(SIGINT, 1)) {
                /* No init process or button pressed twice.  */
-               ip32_machine_power_off();
+               ip32_poweroff(&ip32_rtc_device);
        }
 
-       shuting_down = 1;
+       shutting_down = 1;
        blink_timer.data = POWERDOWN_FREQ;
        blink_timeout(POWERDOWN_FREQ);
 
@@ -136,27 +107,6 @@ static inline void ip32_power_button(void)
        add_timer(&power_timer);
 }
 
-static irqreturn_t ip32_rtc_int(int irq, void *dev_id)
-{
-       unsigned char reg_c;
-
-       reg_c = CMOS_READ(RTC_INTR_FLAGS);
-       if (!(reg_c & RTC_IRQF)) {
-               printk(KERN_WARNING
-                       "%s: RTC IRQ without RTC_IRQF\n", __func__);
-       }
-       /* Wait until interrupt goes away */
-       disable_irq_nosync(MACEISA_RTC_IRQ);
-       init_timer(&debounce_timer);
-       debounce_timer.function = debounce;
-       debounce_timer.expires = jiffies + 50;
-       add_timer(&debounce_timer);
-
-       printk(KERN_DEBUG "Power button pressed\n");
-       ip32_power_button();
-       return IRQ_HANDLED;
-}
-
 static int panic_event(struct notifier_block *this, unsigned long event,
                       void *ptr)
 {
@@ -190,15 +140,12 @@ static __init int ip32_reboot_setup(void)
 
        _machine_restart = ip32_machine_restart;
        _machine_halt = ip32_machine_halt;
-       pm_power_off = ip32_machine_power_off;
+       pm_power_off = ip32_machine_halt;
 
        init_timer(&blink_timer);
        blink_timer.function = blink_timeout;
        atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
-       if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL))
-               panic("Can't allocate MACEISA RTC IRQ");
-
        return 0;
 }
 
index 8686237..12b341d 100644 (file)
@@ -20,6 +20,7 @@ generic-y += param.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += preempt.h
+generic-y += seccomp.h
 generic-y += segment.h
 generic-y += topology.h
 generic-y += trace_clock.h
diff --git a/arch/parisc/include/asm/seccomp.h b/arch/parisc/include/asm/seccomp.h
deleted file mode 100644 (file)
index 015f788..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_PARISC_SECCOMP_H
-#define _ASM_PARISC_SECCOMP_H
-
-#include <linux/unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#define __NR_seccomp_read_32 __NR_read
-#define __NR_seccomp_write_32 __NR_write
-#define __NR_seccomp_exit_32 __NR_exit
-#define __NR_seccomp_sigreturn_32 __NR_rt_sigreturn
-
-#endif /* _ASM_PARISC_SECCOMP_H */
diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..c1818e3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ASM_POWERPC_SECCOMP_H
+#define _ASM_POWERPC_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_POWERPC_SECCOMP_H */
index 7a3f795..79c4068 100644 (file)
@@ -25,7 +25,6 @@ header-y += posix_types.h
 header-y += ps3fb.h
 header-y += ptrace.h
 header-y += resource.h
-header-y += seccomp.h
 header-y += sembuf.h
 header-y += setup.h
 header-y += shmbuf.h
diff --git a/arch/powerpc/include/uapi/asm/seccomp.h b/arch/powerpc/include/uapi/asm/seccomp.h
deleted file mode 100644 (file)
index 00c1d91..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_POWERPC_SECCOMP_H
-#define _ASM_POWERPC_SECCOMP_H
-
-#include <linux/unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#define __NR_seccomp_read_32 __NR_read
-#define __NR_seccomp_write_32 __NR_write
-#define __NR_seccomp_exit_32 __NR_exit
-#define __NR_seccomp_sigreturn_32 __NR_sigreturn
-
-#endif /* _ASM_POWERPC_SECCOMP_H */
index 1c27831..ed7b097 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kref.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
 #include <linux/numa.h>
@@ -322,18 +323,20 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
        unsigned long app_cookie = 0;
        unsigned int my_offset = 0;
        struct vm_area_struct *vma;
+       struct file *exe_file;
        struct mm_struct *mm = spu->mm;
 
        if (!mm)
                goto out;
 
-       down_read(&mm->mmap_sem);
-
-       if (mm->exe_file) {
-               app_cookie = fast_get_dcookie(&mm->exe_file->f_path);
-               pr_debug("got dcookie for %pD\n", mm->exe_file);
+       exe_file = get_mm_exe_file(mm);
+       if (exe_file) {
+               app_cookie = fast_get_dcookie(&exe_file->f_path);
+               pr_debug("got dcookie for %pD\n", exe_file);
+               fput(exe_file);
        }
 
+       down_read(&mm->mmap_sem);
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                if (vma->vm_start > spu_ref || vma->vm_end <= spu_ref)
                        continue;
index adca1bc..5ef8826 100644 (file)
@@ -1,15 +1,10 @@
 #ifndef _ASM_SECCOMP_H
+#define _ASM_SECCOMP_H
 
 #include <linux/unistd.h>
 
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#define __NR_seccomp_read_32 __NR_read
-#define __NR_seccomp_write_32 __NR_write
-#define __NR_seccomp_exit_32 __NR_exit
 #define __NR_seccomp_sigreturn_32 __NR_sigreturn
 
+#include <asm-generic/seccomp.h>
+
 #endif /* _ASM_SECCOMP_H */
index 0f3d7f0..0c8c7c8 100644 (file)
@@ -1,5 +1,20 @@
+#ifndef _ASM_X86_SECCOMP_H
+#define _ASM_X86_SECCOMP_H
+
+#include <asm/unistd.h>
+
 #ifdef CONFIG_X86_32
-# include <asm/seccomp_32.h>
-#else
-# include <asm/seccomp_64.h>
+#define __NR_seccomp_sigreturn         __NR_sigreturn
 #endif
+
+#ifdef CONFIG_COMPAT
+#include <asm/ia32_unistd.h>
+#define __NR_seccomp_read_32           __NR_ia32_read
+#define __NR_seccomp_write_32          __NR_ia32_write
+#define __NR_seccomp_exit_32           __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32      __NR_ia32_sigreturn
+#endif
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_X86_SECCOMP_H */
diff --git a/arch/x86/include/asm/seccomp_32.h b/arch/x86/include/asm/seccomp_32.h
deleted file mode 100644 (file)
index b811d6f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_X86_SECCOMP_32_H
-#define _ASM_X86_SECCOMP_32_H
-
-#include <linux/unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_sigreturn
-
-#endif /* _ASM_X86_SECCOMP_32_H */
diff --git a/arch/x86/include/asm/seccomp_64.h b/arch/x86/include/asm/seccomp_64.h
deleted file mode 100644 (file)
index 84ec1bd..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_X86_SECCOMP_64_H
-#define _ASM_X86_SECCOMP_64_H
-
-#include <linux/unistd.h>
-#include <asm/ia32_unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#define __NR_seccomp_read_32 __NR_ia32_read
-#define __NR_seccomp_write_32 __NR_ia32_write
-#define __NR_seccomp_exit_32 __NR_ia32_exit
-#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
-
-#endif /* _ASM_X86_SECCOMP_64_H */
index 05abae8..a0ef4f7 100644 (file)
@@ -15,6 +15,7 @@
 #include "clk-kona.h"
 
 #include <linux/delay.h>
+#include <linux/kernel.h>
 
 /*
  * "Policies" affect the frequencies of bus clocks provided by a
@@ -51,21 +52,6 @@ static inline u32 bitfield_replace(u32 reg_val, u32 shift, u32 width, u32 val)
 
 /* Divider and scaling helpers */
 
-/*
- * Implement DIV_ROUND_CLOSEST() for 64-bit dividend and both values
- * unsigned.  Note that unlike do_div(), the remainder is discarded
- * and the return value is the quotient (not the remainder).
- */
-u64 do_div_round_closest(u64 dividend, unsigned long divisor)
-{
-       u64 result;
-
-       result = dividend + ((u64)divisor >> 1);
-       (void)do_div(result, divisor);
-
-       return result;
-}
-
 /* Convert a divider into the scaled divisor value it represents. */
 static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
 {
@@ -87,7 +73,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
        combined = (u64)div_value * BILLION + billionths;
        combined <<= div->u.s.frac_width;
 
-       return do_div_round_closest(combined, BILLION);
+       return DIV_ROUND_CLOSEST_ULL(combined, BILLION);
 }
 
 /* The scaled minimum divisor representable by a divider */
@@ -731,7 +717,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu,
                scaled_rate = scale_rate(pre_div, parent_rate);
                scaled_rate = scale_rate(div, scaled_rate);
                scaled_div = divider_read_scaled(ccu, pre_div);
-               scaled_parent_rate = do_div_round_closest(scaled_rate,
+               scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate,
                                                        scaled_div);
        } else  {
                scaled_parent_rate = scale_rate(div, parent_rate);
@@ -743,7 +729,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu,
         * rate.
         */
        scaled_div = divider_read_scaled(ccu, div);
-       result = do_div_round_closest(scaled_parent_rate, scaled_div);
+       result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, scaled_div);
 
        return (unsigned long)result;
 }
@@ -790,7 +776,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div,
                scaled_rate = scale_rate(pre_div, parent_rate);
                scaled_rate = scale_rate(div, scaled_rate);
                scaled_pre_div = divider_read_scaled(ccu, pre_div);
-               scaled_parent_rate = do_div_round_closest(scaled_rate,
+               scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate,
                                                        scaled_pre_div);
        } else {
                scaled_parent_rate = scale_rate(div, parent_rate);
@@ -802,7 +788,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div,
         * the best we can do.
         */
        if (!divider_is_fixed(div)) {
-               best_scaled_div = do_div_round_closest(scaled_parent_rate,
+               best_scaled_div = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate,
                                                        rate);
                min_scaled_div = scaled_div_min(div);
                max_scaled_div = scaled_div_max(div);
@@ -815,7 +801,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div,
        }
 
        /* OK, figure out the resulting rate */
-       result = do_div_round_closest(scaled_parent_rate, best_scaled_div);
+       result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, best_scaled_div);
 
        if (scaled_div)
                *scaled_div = best_scaled_div;
index 2537b30..6849a64 100644 (file)
@@ -503,7 +503,6 @@ extern struct clk_ops kona_peri_clk_ops;
 
 /* Externally visible functions */
 
-extern u64 do_div_round_closest(u64 dividend, unsigned long divisor);
 extern u64 scaled_div_max(struct bcm_clk_div *div);
 extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value,
                                u32 billionths);
index 4058079..b8a5fa1 100644 (file)
@@ -190,12 +190,6 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
 static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
 
-/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
-static u64 div_round64(u64 dividend, u32 divisor)
-{
-       return div_u64(dividend + (divisor / 2), divisor);
-}
-
 /*
  * Try detecting repeating patterns by keeping track of the last 8
  * intervals, and checking if the standard deviation of that set
@@ -317,7 +311,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * operands are 32 bits.
         * Make sure to round up for half microseconds.
         */
-       data->predicted_us = div_round64((uint64_t)data->next_timer_us *
+       data->predicted_us = DIV_ROUND_CLOSEST_ULL((uint64_t)data->next_timer_us *
                                         data->correction_factor[data->bucket],
                                         RESOLUTION * DECAY);
 
index eef79cc..ba243db 100644 (file)
@@ -36,9 +36,6 @@
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_rect.h>
 
-#define DIV_ROUND_CLOSEST_ULL(ll, d)   \
-({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
-
 /**
  * _wait_for - magic (register) wait macro
  *
index d8686ce..08532d4 100644 (file)
@@ -30,6 +30,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/kernel.h>
 #include <linux/moduleparam.h>
 #include "intel_drv.h"
 
index d1542b7..4d28150 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/jiffies.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/util_macros.h>
 
 #include <linux/platform_data/ina2xx.h>
 
@@ -141,19 +142,6 @@ static const struct ina2xx_config ina2xx_config[] = {
  */
 static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
 
-static int ina226_avg_bits(int avg)
-{
-       int i;
-
-       /* Get the closest average from the tab. */
-       for (i = 0; i < ARRAY_SIZE(ina226_avg_tab) - 1; i++) {
-               if (avg <= (ina226_avg_tab[i] + ina226_avg_tab[i + 1]) / 2)
-                       break;
-       }
-
-       return i; /* Return 0b0111 for values greater than 1024. */
-}
-
 static int ina226_reg_to_interval(u16 config)
 {
        int avg = ina226_avg_tab[INA226_READ_AVG(config)];
@@ -171,7 +159,8 @@ static u16 ina226_interval_to_reg(int interval, u16 config)
 
        avg = DIV_ROUND_CLOSEST(interval * 1000,
                                INA226_TOTAL_CONV_TIME_DEFAULT);
-       avg_bits = ina226_avg_bits(avg);
+       avg_bits = find_closest(avg, ina226_avg_tab,
+                               ARRAY_SIZE(ina226_avg_tab));
 
        return (config & ~INA226_AVG_RD_MASK) | INA226_SHIFT_AVG(avg_bits);
 }
index 2b4b419..6ff773f 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/util_macros.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -190,15 +191,7 @@ static const int lm85_range_map[] = {
 
 static int RANGE_TO_REG(long range)
 {
-       int i;
-
-       /* Find the closest match */
-       for (i = 0; i < 15; ++i) {
-               if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2)
-                       break;
-       }
-
-       return i;
+       return find_closest(range, lm85_range_map, ARRAY_SIZE(lm85_range_map));
 }
 #define RANGE_FROM_REG(val)    lm85_range_map[(val) & 0x0f]
 
@@ -209,16 +202,12 @@ static const int lm85_freq_map[8] = { /* 1 Hz */
 static const int adm1027_freq_map[8] = { /* 1 Hz */
        11, 15, 22, 29, 35, 44, 59, 88
 };
+#define FREQ_MAP_LEN   8
 
-static int FREQ_TO_REG(const int *map, unsigned long freq)
+static int FREQ_TO_REG(const int *map,
+                      unsigned int map_size, unsigned long freq)
 {
-       int i;
-
-       /* Find the closest match */
-       for (i = 0; i < 7; ++i)
-               if (freq <= (map[i] + map[i + 1]) / 2)
-                       break;
-       return i;
+       return find_closest(freq, map, map_size);
 }
 
 static int FREQ_FROM_REG(const int *map, u8 reg)
@@ -828,7 +817,8 @@ static ssize_t set_pwm_freq(struct device *dev,
                data->cfg5 &= ~ADT7468_HFPWM;
                lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5);
        } else {                                        /* Low freq. mode */
-               data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val);
+               data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map,
+                                                FREQ_MAP_LEN, val);
                lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
                                 (data->zone[nr].range << 4)
                                 | data->pwm_freq[nr]);
index 2189413..49276bb 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
+#include <linux/util_macros.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = {
@@ -308,11 +309,8 @@ static u8 pwm_freq_to_reg(unsigned long val, u16 clkin)
        unsigned long best0, best1;
 
        /* Best fit for cksel = 0 */
-       for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) {
-               if (val > (pwm_freq_cksel0[reg0] +
-                          pwm_freq_cksel0[reg0 + 1]) / 2)
-                       break;
-       }
+       reg0 = find_closest_descending(val, pwm_freq_cksel0,
+                                      ARRAY_SIZE(pwm_freq_cksel0));
        if (val < 375)  /* cksel = 1 can't beat this */
                return reg0;
        best0 = pwm_freq_cksel0[reg0];
index 149fdca..72b0e2d 100644 (file)
@@ -79,7 +79,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
-       if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = 0x4000 - DIV_ROUND_CLOSEST_ULL(num, 41000);
        buf[0] = (if_ctl >> 8) & 0x3f;
        buf[1] = (if_ctl >> 0) & 0xff;
 
index 422e84b..490e090 100644 (file)
@@ -244,12 +244,6 @@ error:
        return ret;
 }
 
-/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
-u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
-{
-       return div_u64(dividend + (divisor / 2), divisor);
-}
-
 static int cxd2820r_set_frontend(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
index 7ff5f60..4b42895 100644 (file)
@@ -64,8 +64,6 @@ int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
 int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
        int len);
 
-u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor);
-
 int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
        int len);
 
index 51401d0..008cb2a 100644 (file)
@@ -103,7 +103,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
-       if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000);
        buf[0] = ((if_ctl >> 16) & 0xff);
        buf[1] = ((if_ctl >>  8) & 0xff);
        buf[2] = ((if_ctl >>  0) & 0xff);
index 9c0c4f4..35fe364 100644 (file)
@@ -120,7 +120,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
-       if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000);
        buf[0] = ((if_ctl >> 16) & 0xff);
        buf[1] = ((if_ctl >>  8) & 0xff);
        buf[2] = ((if_ctl >>  0) & 0xff);
index fc145d2..922a750 100644 (file)
@@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
 
                if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
                        if (msb->data_dir == READ) {
-                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                               for (cnt = 0; cnt < msb->current_seg; cnt++) {
                                        t_len += msb->req_sg[cnt].length
                                                 / msb->page_size;
 
@@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
                                                t_len += msb->current_page - 1;
 
                                        t_len *= msb->page_size;
+                               }
                        }
                } else
                        t_len = blk_rq_bytes(msb->block_req);
index d93b2b6..82f7000 100644 (file)
@@ -21,6 +21,7 @@
  * objects.
  */
 
+#include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
@@ -224,10 +225,18 @@ static inline unsigned long fast_get_dcookie(struct path *path)
 static unsigned long get_exec_dcookie(struct mm_struct *mm)
 {
        unsigned long cookie = NO_COOKIE;
+       struct file *exe_file;
 
-       if (mm && mm->exe_file)
-               cookie = fast_get_dcookie(&mm->exe_file->f_path);
+       if (!mm)
+               goto done;
+
+       exe_file = get_mm_exe_file(mm);
+       if (!exe_file)
+               goto done;
 
+       cookie = fast_get_dcookie(&exe_file->f_path);
+       fput(exe_file);
+done:
        return cookie;
 }
 
@@ -236,6 +245,8 @@ static unsigned long get_exec_dcookie(struct mm_struct *mm)
  * pair that can then be added to the global event buffer. We make
  * sure to do this lookup before a mm->mmap modification happens so
  * we don't lose track.
+ *
+ * The caller must ensure the mm is not nil (ie: not a kernel thread).
  */
 static unsigned long
 lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
@@ -243,6 +254,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
        unsigned long cookie = NO_COOKIE;
        struct vm_area_struct *vma;
 
+       down_read(&mm->mmap_sem);
        for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
 
                if (addr < vma->vm_start || addr >= vma->vm_end)
@@ -262,6 +274,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
 
        if (!vma)
                cookie = INVALID_COOKIE;
+       up_read(&mm->mmap_sem);
 
        return cookie;
 }
@@ -402,20 +415,9 @@ static void release_mm(struct mm_struct *mm)
 {
        if (!mm)
                return;
-       up_read(&mm->mmap_sem);
        mmput(mm);
 }
 
-
-static struct mm_struct *take_tasks_mm(struct task_struct *task)
-{
-       struct mm_struct *mm = get_task_mm(task);
-       if (mm)
-               down_read(&mm->mmap_sem);
-       return mm;
-}
-
-
 static inline int is_code(unsigned long val)
 {
        return val == ESCAPE_CODE;
@@ -532,7 +534,7 @@ void sync_buffer(int cpu)
                                new = (struct task_struct *)val;
                                oldmm = mm;
                                release_mm(oldmm);
-                               mm = take_tasks_mm(new);
+                               mm = get_task_mm(new);
                                if (mm != oldmm)
                                        cookie = get_exec_dcookie(mm);
                                add_user_ctx_switch(new, cookie);
index b5b5c3d..6149ae0 100644 (file)
@@ -1111,6 +1111,16 @@ config RTC_DRV_DAVINCI
          This driver can also be built as a module. If so, the module
          will be called rtc-davinci.
 
+config RTC_DRV_DIGICOLOR
+       tristate "Conexant Digicolor RTC"
+       depends on ARCH_DIGICOLOR
+       help
+         If you say yes here you get support for the RTC on Conexant
+         Digicolor platforms. This currently includes the CX92755 SoC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-digicolor.
+
 config RTC_DRV_IMXDI
        tristate "Freescale IMX DryIce Real Time Clock"
        depends on ARCH_MXC
@@ -1121,11 +1131,11 @@ config RTC_DRV_IMXDI
           will be called "rtc-imxdi".
 
 config RTC_DRV_OMAP
-       tristate "TI OMAP1"
-       depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
+       tristate "TI OMAP Real Time Clock"
+       depends on ARCH_OMAP || ARCH_DAVINCI
        help
          Say "yes" here to support the on chip real time clock
-         present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x.
+         present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
 
          This driver can also be built as a module, if so, module
          will be called rtc-omap.
index 69c8706..c31731c 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_DA9052)  += rtc-da9052.o
 obj-$(CONFIG_RTC_DRV_DA9055)   += rtc-da9055.o
 obj-$(CONFIG_RTC_DRV_DA9063)   += rtc-da9063.o
 obj-$(CONFIG_RTC_DRV_DAVINCI)  += rtc-davinci.o
+obj-$(CONFIG_RTC_DRV_DIGICOLOR)        += rtc-digicolor.o
 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
 obj-$(CONFIG_RTC_DRV_VRTC)     += rtc-mrst.o
 obj-$(CONFIG_RTC_DRV_DS1216)   += rtc-ds1216.o
index c29ba7e..ea2a315 100644 (file)
@@ -221,15 +221,15 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
        rtc->pie_timer.function = rtc_pie_update_irq;
        rtc->pie_enabled = 0;
 
+       strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
+       dev_set_name(&rtc->dev, "rtc%d", id);
+
        /* Check to see if there is an ALARM already set in hw */
        err = __rtc_read_alarm(rtc, &alrm);
 
        if (!err && !rtc_valid_tm(&alrm.time))
                rtc_initialize_alarm(rtc, &alrm);
 
-       strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
-       dev_set_name(&rtc->dev, "rtc%d", id);
-
        rtc_dev_prepare(rtc);
 
        err = device_register(&rtc->dev);
index 6c719f2..e1cfa06 100644 (file)
@@ -9,6 +9,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/rtc.h>
 
 /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
@@ -32,8 +34,8 @@ static int __init rtc_hctosys(void)
        struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
 
        if (rtc == NULL) {
-               pr_err("%s: unable to open rtc device (%s)\n",
-                       __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
+               pr_info("unable to open rtc device (%s)\n",
+                       CONFIG_RTC_HCTOSYS_DEVICE);
                goto err_open;
        }
 
index d43ee40..166fc60 100644 (file)
@@ -31,13 +31,14 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
                memset(tm, 0, sizeof(struct rtc_time));
                err = rtc->ops->read_time(rtc->dev.parent, tm);
                if (err < 0) {
-                       dev_err(&rtc->dev, "read_time: fail to read\n");
+                       dev_dbg(&rtc->dev, "read_time: fail to read: %d\n",
+                               err);
                        return err;
                }
 
                err = rtc_valid_tm(tm);
                if (err < 0)
-                       dev_err(&rtc->dev, "read_time: rtc_time isn't valid\n");
+                       dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n");
        }
        return err;
 }
index cfc2ef9..b5cbc1b 100644 (file)
@@ -881,7 +881,7 @@ static const struct rtc_class_ops rtc_ops = {
        .alarm_irq_enable = abb5zes3_rtc_alarm_irq_enable,
 };
 
-static struct regmap_config abb5zes3_rtc_regmap_config = {
+static const struct regmap_config abb5zes3_rtc_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 };
index b283a1a..35efd3f 100644 (file)
@@ -37,9 +37,9 @@
 #include "rtc-at91rm9200.h"
 
 #define at91_rtc_read(field) \
-       __raw_readl(at91_rtc_regs + field)
+       readl_relaxed(at91_rtc_regs + field)
 #define at91_rtc_write(field, val) \
-       __raw_writel((val), at91_rtc_regs + field)
+       writel_relaxed((val), at91_rtc_regs + field)
 
 #define AT91_RTC_EPOCH         1900UL  /* just like arch/arm/common/rtctime.c */
 
index 87647f4..a82556a 100644 (file)
@@ -28,6 +28,9 @@
  * interrupts disabled, holding the global rtc_lock, to exclude those
  * other drivers and utilities on correctly configured systems.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -385,8 +388,7 @@ static bool alarm_disable_quirk;
 static int __init set_alarm_disable_quirk(const struct dmi_system_id *id)
 {
        alarm_disable_quirk = true;
-       pr_info("rtc-cmos: BIOS has alarm-disable quirk. ");
-       pr_info("RTC alarms disabled\n");
+       pr_info("BIOS has alarm-disable quirk - RTC alarms disabled\n");
        return 0;
 }
 
index 613c43b..1ba4371 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 
 #include <linux/mfd/da9052/da9052.h>
 #include <linux/mfd/da9052/reg.h>
@@ -23,6 +24,8 @@
 #define rtc_err(rtc, fmt, ...) \
                dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
 
+#define DA9052_GET_TIME_RETRIES 5
+
 struct da9052_rtc {
        struct rtc_device *rtc;
        struct da9052 *da9052;
@@ -58,22 +61,43 @@ static irqreturn_t da9052_rtc_irq(int irq, void *data)
 static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
 {
        int ret;
-       uint8_t v[5];
+       uint8_t v[2][5];
+       int idx = 1;
+       int timeout = DA9052_GET_TIME_RETRIES;
 
-       ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v);
-       if (ret != 0) {
+       ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, &v[0][0]);
+       if (ret) {
                rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
                return ret;
        }
 
-       rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100;
-       rtc_tm->tm_mon  = (v[3] & DA9052_RTC_MONTH) - 1;
-       rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY;
-       rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR;
-       rtc_tm->tm_min  = v[0] & DA9052_RTC_MIN;
+       do {
+               ret = da9052_group_read(rtc->da9052,
+                                       DA9052_ALARM_MI_REG, 5, &v[idx][0]);
+               if (ret) {
+                       rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
+                       return ret;
+               }
 
-       ret = rtc_valid_tm(rtc_tm);
-       return ret;
+               if (memcmp(&v[0][0], &v[1][0], 5) == 0) {
+                       rtc_tm->tm_year = (v[0][4] & DA9052_RTC_YEAR) + 100;
+                       rtc_tm->tm_mon  = (v[0][3] & DA9052_RTC_MONTH) - 1;
+                       rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
+                       rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
+                       rtc_tm->tm_min  = v[0][0] & DA9052_RTC_MIN;
+
+                       ret = rtc_valid_tm(rtc_tm);
+                       return ret;
+               }
+
+               idx = (1-idx);
+               msleep(20);
+
+       } while (timeout--);
+
+       rtc_err(rtc, "Timed out reading alarm time\n");
+
+       return -EIO;
 }
 
 static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
@@ -135,24 +159,45 @@ static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc)
 static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
 {
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
-       uint8_t v[6];
        int ret;
+       uint8_t v[2][6];
+       int idx = 1;
+       int timeout = DA9052_GET_TIME_RETRIES;
 
-       ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
-       if (ret < 0) {
+       ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, &v[0][0]);
+       if (ret) {
                rtc_err(rtc, "Failed to read RTC time : %d\n", ret);
                return ret;
        }
 
-       rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100;
-       rtc_tm->tm_mon  = (v[4] & DA9052_RTC_MONTH) - 1;
-       rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY;
-       rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR;
-       rtc_tm->tm_min  = v[1] & DA9052_RTC_MIN;
-       rtc_tm->tm_sec  = v[0] & DA9052_RTC_SEC;
+       do {
+               ret = da9052_group_read(rtc->da9052,
+                                       DA9052_COUNT_S_REG, 6, &v[idx][0]);
+               if (ret) {
+                       rtc_err(rtc, "Failed to read RTC time : %d\n", ret);
+                       return ret;
+               }
 
-       ret = rtc_valid_tm(rtc_tm);
-       return ret;
+               if (memcmp(&v[0][0], &v[1][0], 6) == 0) {
+                       rtc_tm->tm_year = (v[0][5] & DA9052_RTC_YEAR) + 100;
+                       rtc_tm->tm_mon  = (v[0][4] & DA9052_RTC_MONTH) - 1;
+                       rtc_tm->tm_mday = v[0][3] & DA9052_RTC_DAY;
+                       rtc_tm->tm_hour = v[0][2] & DA9052_RTC_HOUR;
+                       rtc_tm->tm_min  = v[0][1] & DA9052_RTC_MIN;
+                       rtc_tm->tm_sec  = v[0][0] & DA9052_RTC_SEC;
+
+                       ret = rtc_valid_tm(rtc_tm);
+                       return ret;
+               }
+
+               idx = (1-idx);
+               msleep(20);
+
+       } while (timeout--);
+
+       rtc_err(rtc, "Timed out reading time\n");
+
+       return -EIO;
 }
 
 static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -161,6 +206,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
        uint8_t v[6];
        int ret;
 
+       /* DA9052 only has 6 bits for year - to represent 2000-2063 */
+       if ((tm->tm_year < 100) || (tm->tm_year > 163))
+               return -EINVAL;
+
        rtc = dev_get_drvdata(dev);
 
        v[0] = tm->tm_sec;
@@ -198,6 +247,10 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_time *tm = &alrm->time;
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 
+       /* DA9052 only has 6 bits for year - to represent 2000-2063 */
+       if ((tm->tm_year < 100) || (tm->tm_year > 163))
+               return -EINVAL;
+
        ret = da9052_rtc_enable_alarm(rtc, 0);
        if (ret < 0)
                return ret;
@@ -256,6 +309,8 @@ static int da9052_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       device_init_wakeup(&pdev->dev, true);
+
        rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                                       &da9052_rtc_ops, THIS_MODULE);
        return PTR_ERR_OR_ZERO(rtc->rtc);
diff --git a/drivers/rtc/rtc-digicolor.c b/drivers/rtc/rtc-digicolor.c
new file mode 100644 (file)
index 0000000..8d05596
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Real Time Clock driver for Conexant Digicolor
+ *
+ * Copyright (C) 2015 Paradox Innovation Ltd.
+ *
+ * Author: Baruch Siach <baruch@tkos.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#define DC_RTC_CONTROL         0x0
+#define DC_RTC_TIME            0x8
+#define DC_RTC_REFERENCE       0xc
+#define DC_RTC_ALARM           0x10
+#define DC_RTC_INTFLAG_CLEAR   0x14
+#define DC_RTC_INTENABLE       0x16
+
+#define DC_RTC_CMD_MASK                0xf
+#define DC_RTC_GO_BUSY         BIT(7)
+
+#define CMD_NOP                        0
+#define CMD_RESET              1
+#define CMD_WRITE              3
+#define CMD_READ               4
+
+#define CMD_DELAY_US           (10*1000)
+#define CMD_TIMEOUT_US         (500*CMD_DELAY_US)
+
+struct dc_rtc {
+       struct rtc_device       *rtc_dev;
+       void __iomem            *regs;
+};
+
+static int dc_rtc_cmds(struct dc_rtc *rtc, const u8 *cmds, int len)
+{
+       u8 val;
+       int i, ret;
+
+       for (i = 0; i < len; i++) {
+               writeb_relaxed((cmds[i] & DC_RTC_CMD_MASK) | DC_RTC_GO_BUSY,
+                              rtc->regs + DC_RTC_CONTROL);
+               ret = readb_relaxed_poll_timeout(
+                       rtc->regs + DC_RTC_CONTROL, val,
+                       !(val & DC_RTC_GO_BUSY), CMD_DELAY_US, CMD_TIMEOUT_US);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int dc_rtc_read(struct dc_rtc *rtc, unsigned long *val)
+{
+       static const u8 read_cmds[] = {CMD_READ, CMD_NOP};
+       u32 reference, time1, time2;
+       int ret;
+
+       ret = dc_rtc_cmds(rtc, read_cmds, ARRAY_SIZE(read_cmds));
+       if (ret < 0)
+               return ret;
+
+       reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE);
+       time1 = readl_relaxed(rtc->regs + DC_RTC_TIME);
+       /* Read twice to ensure consistency */
+       while (1) {
+               time2 = readl_relaxed(rtc->regs + DC_RTC_TIME);
+               if (time1 == time2)
+                       break;
+               time1 = time2;
+       }
+
+       *val = reference + time1;
+       return 0;
+}
+
+static int dc_rtc_write(struct dc_rtc *rtc, u32 val)
+{
+       static const u8 write_cmds[] = {CMD_WRITE, CMD_NOP, CMD_RESET, CMD_NOP};
+
+       writel_relaxed(val, rtc->regs + DC_RTC_REFERENCE);
+       return dc_rtc_cmds(rtc, write_cmds, ARRAY_SIZE(write_cmds));
+}
+
+static int dc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct dc_rtc *rtc = dev_get_drvdata(dev);
+       unsigned long now;
+       int ret;
+
+       ret = dc_rtc_read(rtc, &now);
+       if (ret < 0)
+               return ret;
+       rtc_time64_to_tm(now, tm);
+
+       return 0;
+}
+
+static int dc_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+       struct dc_rtc *rtc = dev_get_drvdata(dev);
+
+       return dc_rtc_write(rtc, secs);
+}
+
+static int dc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct dc_rtc *rtc = dev_get_drvdata(dev);
+       u32 alarm_reg, reference;
+       unsigned long now;
+       int ret;
+
+       alarm_reg = readl_relaxed(rtc->regs + DC_RTC_ALARM);
+       reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE);
+       rtc_time64_to_tm(reference + alarm_reg, &alarm->time);
+
+       ret = dc_rtc_read(rtc, &now);
+       if (ret < 0)
+               return ret;
+
+       alarm->pending = alarm_reg + reference > now;
+       alarm->enabled = readl_relaxed(rtc->regs + DC_RTC_INTENABLE);
+
+       return 0;
+}
+
+static int dc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct dc_rtc *rtc = dev_get_drvdata(dev);
+       time64_t alarm_time;
+       u32 reference;
+
+       alarm_time = rtc_tm_to_time64(&alarm->time);
+
+       reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE);
+       writel_relaxed(alarm_time - reference, rtc->regs + DC_RTC_ALARM);
+
+       writeb_relaxed(!!alarm->enabled, rtc->regs + DC_RTC_INTENABLE);
+
+       return 0;
+}
+
+static int dc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct dc_rtc *rtc = dev_get_drvdata(dev);
+
+       writeb_relaxed(!!enabled, rtc->regs + DC_RTC_INTENABLE);
+
+       return 0;
+}
+
+static struct rtc_class_ops dc_rtc_ops = {
+       .read_time              = dc_rtc_read_time,
+       .set_mmss               = dc_rtc_set_mmss,
+       .read_alarm             = dc_rtc_read_alarm,
+       .set_alarm              = dc_rtc_set_alarm,
+       .alarm_irq_enable       = dc_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t dc_rtc_irq(int irq, void *dev_id)
+{
+       struct dc_rtc *rtc = dev_id;
+
+       writeb_relaxed(1, rtc->regs + DC_RTC_INTFLAG_CLEAR);
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+       return IRQ_HANDLED;
+}
+
+static int __init dc_rtc_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct dc_rtc *rtc;
+       int irq, ret;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rtc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rtc->regs))
+               return PTR_ERR(rtc->regs);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+       ret = devm_request_irq(&pdev->dev, irq, dc_rtc_irq, 0, pdev->name, rtc);
+       if (ret < 0)
+               return ret;
+
+       platform_set_drvdata(pdev, rtc);
+       rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
+                                               &dc_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc_dev))
+               return PTR_ERR(rtc->rtc_dev);
+
+       return 0;
+}
+
+static const struct of_device_id dc_dt_ids[] = {
+       { .compatible = "cnxt,cx92755-rtc" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dc_dt_ids);
+
+static struct platform_driver dc_rtc_driver = {
+       .driver = {
+               .name = "digicolor_rtc",
+               .of_match_table = of_match_ptr(dc_dt_ids),
+       },
+};
+module_platform_driver_probe(dc_rtc_driver, dc_rtc_probe);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Conexant Digicolor Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
index 8605fde..167783f 100644 (file)
@@ -18,6 +18,8 @@
  * "Sending and receiving", using SMBus level communication is preferred.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -406,7 +408,7 @@ static int ds1374_wdt_settimeout(unsigned int timeout)
        /* Set new watchdog time */
        ret = ds1374_write_rtc(save_client, timeout, DS1374_REG_WDALM0, 3);
        if (ret) {
-               pr_info("rtc-ds1374 - couldn't set new watchdog time\n");
+               pr_info("couldn't set new watchdog time\n");
                goto out;
        }
 
@@ -539,12 +541,12 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                if (options & WDIOS_DISABLECARD) {
-                       pr_info("rtc-ds1374: disable watchdog\n");
+                       pr_info("disable watchdog\n");
                        ds1374_wdt_disable();
                }
 
                if (options & WDIOS_ENABLECARD) {
-                       pr_info("rtc-ds1374: enable watchdog\n");
+                       pr_info("enable watchdog\n");
                        ds1374_wdt_settimeout(wdt_margin);
                        ds1374_wdt_ping();
                }
index 803869c..818a363 100644 (file)
@@ -16,6 +16,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bcd.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -799,7 +801,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
        struct platform_device *pdev = to_platform_device(dev);
        struct ds1685_priv *rtc = platform_get_drvdata(pdev);
        u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8];
-       char *model = '\0';
+       char *model;
 #ifdef CONFIG_RTC_DS1685_PROC_REGS
        char bits[NUM_REGS][(NUM_BITS * NUM_SPACES) + NUM_BITS + 1];
 #endif
@@ -2139,7 +2141,6 @@ ds1685_rtc_remove(struct platform_device *pdev)
 static struct platform_driver ds1685_rtc_driver = {
        .driver         = {
                .name   = "rtc-ds1685",
-               .owner  = THIS_MODULE,
        },
        .probe          = ds1685_rtc_probe,
        .remove         = ds1685_rtc_remove,
@@ -2175,7 +2176,7 @@ module_exit(ds1685_rtc_exit);
  * ds1685_rtc_poweroff - uses the RTC chip to power the system off.
  * @pdev: pointer to platform_device structure.
  */
-extern void __noreturn
+void __noreturn
 ds1685_rtc_poweroff(struct platform_device *pdev)
 {
        u8 ctrla, ctrl4a, ctrl4b;
@@ -2183,7 +2184,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
 
        /* Check for valid RTC data, else, spin forever. */
        if (unlikely(!pdev)) {
-               pr_emerg("rtc-ds1685: platform device data not available, spinning forever ...\n");
+               pr_emerg("platform device data not available, spinning forever ...\n");
                unreachable();
        } else {
                /* Get the rtc data. */
index adaf06c..7e48e53 100644 (file)
@@ -15,6 +15,8 @@
  * "Sending and receiving", using SMBus level communication is preferred.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -373,8 +375,8 @@ static void ds3232_work(struct work_struct *work)
        if (stat & DS3232_REG_SR_A1F) {
                control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
                if (control < 0) {
-                       pr_warn("Read DS3232 Control Register error."
-                               "Disable IRQ%d.\n", client->irq);
+                       pr_warn("Read Control Register error - Disable IRQ%d\n",
+                               client->irq);
                } else {
                        /* disable alarm1 interrupt */
                        control &= ~(DS3232_REG_CR_A1IE);
index b40fbe3..1a7f1d1 100644 (file)
@@ -8,6 +8,9 @@
  * Copyright (C) 1999-2000 VA Linux Systems
  * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index fccf366..4f4930a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/module.h>
+#include <linux/of.h>
 
 /* Registers */
 #define EM3027_REG_ON_OFF_CTRL 0x00
@@ -135,10 +136,20 @@ static struct i2c_device_id em3027_id[] = {
        { "em3027", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c, em3027_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id em3027_of_match[] = {
+       { .compatible = "emmicro,em3027", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, em3027_of_match);
+#endif
 
 static struct i2c_driver em3027_driver = {
        .driver = {
                   .name = "rtc-em3027",
+                  .of_match_table = of_match_ptr(em3027_of_match),
        },
        .probe = &em3027_probe,
        .id_table = em3027_id,
index b936bb4..0f710e9 100644 (file)
@@ -66,7 +66,7 @@
 #define HYM8563_ALM_BIT_DISABLE        BIT(7)
 
 #define HYM8563_CLKOUT         0x0d
-#define HYM8563_CLKOUT_DISABLE BIT(7)
+#define HYM8563_CLKOUT_ENABLE  BIT(7)
 #define HYM8563_CLKOUT_32768   0
 #define HYM8563_CLKOUT_1024    1
 #define HYM8563_CLKOUT_32      2
@@ -309,7 +309,7 @@ static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw,
        struct i2c_client *client = hym8563->client;
        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 
-       if (ret < 0 || ret & HYM8563_CLKOUT_DISABLE)
+       if (ret < 0)
                return 0;
 
        ret &= HYM8563_CLKOUT_MASK;
@@ -360,9 +360,9 @@ static int hym8563_clkout_control(struct clk_hw *hw, bool enable)
                return ret;
 
        if (enable)
-               ret &= ~HYM8563_CLKOUT_DISABLE;
+               ret |= HYM8563_CLKOUT_ENABLE;
        else
-               ret |= HYM8563_CLKOUT_DISABLE;
+               ret &= ~HYM8563_CLKOUT_ENABLE;
 
        return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);
 }
@@ -386,7 +386,7 @@ static int hym8563_clkout_is_prepared(struct clk_hw *hw)
        if (ret < 0)
                return ret;
 
-       return !(ret & HYM8563_CLKOUT_DISABLE);
+       return !!(ret & HYM8563_CLKOUT_ENABLE);
 }
 
 static const struct clk_ops hym8563_clkout_ops = {
@@ -407,7 +407,7 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
        int ret;
 
        ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,
-                                               HYM8563_CLKOUT_DISABLE);
+                                               0);
        if (ret < 0)
                return ERR_PTR(ret);
 
index 7ff7427..a82937e 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bcd.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -513,12 +515,12 @@ static int wdt_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                if (rv & WDIOS_DISABLECARD) {
-                       pr_info("rtc-m41t80: disable watchdog\n");
+                       pr_info("disable watchdog\n");
                        wdt_disable();
                }
 
                if (rv & WDIOS_ENABLECARD) {
-                       pr_info("rtc-m41t80: enable watchdog\n");
+                       pr_info("enable watchdog\n");
                        wdt_ping();
                }
 
index 9d71328..7632a87 100644 (file)
@@ -12,6 +12,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/rtc.h>
 #include <linux/delay.h>
@@ -103,8 +105,8 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
        data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
 
        if (tm->tm_year < 100) {
-               pr_warn("%s: MAX77686 RTC cannot handle the year %d."
-                       "Assume it's 2000.\n", __func__, 1900 + tm->tm_year);
+               pr_warn("RTC cannot handle the year %d.  Assume it's 2000.\n",
+                       1900 + tm->tm_year);
                return -EINVAL;
        }
        return 0;
index 67fbe55..9e02bcd 100644 (file)
@@ -12,6 +12,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/rtc.h>
 #include <linux/delay.h>
@@ -107,8 +109,8 @@ static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
        data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
 
        if (tm->tm_year < 100) {
-               pr_warn("%s: MAX8997 RTC cannot handle the year %d."
-                       "Assume it's 2000.\n", __func__, 1900 + tm->tm_year);
+               pr_warn("RTC cannot handle the year %d.  Assume it's 2000.\n",
+                       1900 + tm->tm_year);
                return -EINVAL;
        }
        return 0;
@@ -424,7 +426,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
 
        val = 0;
        max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
-       pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
+       pr_info("WTSR_SMPL(0x%02x)\n", val);
 }
 
 static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
index 9bf877b..c1c5c4e 100644 (file)
@@ -7,6 +7,8 @@
  *  Copyright (C) 1993 Hamish Macdonald
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -111,7 +113,7 @@ static void msm6242_lock(struct msm6242_priv *priv)
        }
 
        if (!cnt)
-               pr_warn("msm6242: timed out waiting for RTC (0x%x)\n",
+               pr_warn("timed out waiting for RTC (0x%x)\n",
                        msm6242_read(priv, MSM6242_CD));
 }
 
index 8e5851a..8b6355f 100644 (file)
 #define        KICK0_VALUE                     0x83e70b13
 #define        KICK1_VALUE                     0x95a4f1e0
 
+struct omap_rtc;
+
 struct omap_rtc_device_type {
        bool has_32kclk_en;
-       bool has_kicker;
        bool has_irqwakeen;
        bool has_pmic_mode;
        bool has_power_up_reset;
+       void (*lock)(struct omap_rtc *rtc);
+       void (*unlock)(struct omap_rtc *rtc);
 };
 
 struct omap_rtc {
@@ -156,6 +159,26 @@ static inline void rtc_writel(struct omap_rtc *rtc, unsigned int reg, u32 val)
        writel(val, rtc->base + reg);
 }
 
+static void am3352_rtc_unlock(struct omap_rtc *rtc)
+{
+       rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE);
+       rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE);
+}
+
+static void am3352_rtc_lock(struct omap_rtc *rtc)
+{
+       rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0);
+       rtc_writel(rtc, OMAP_RTC_KICK1_REG, 0);
+}
+
+static void default_rtc_unlock(struct omap_rtc *rtc)
+{
+}
+
+static void default_rtc_lock(struct omap_rtc *rtc)
+{
+}
+
 /*
  * We rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
@@ -186,7 +209,9 @@ static irqreturn_t rtc_irq(int irq, void *dev_id)
 
        /* alarm irq? */
        if (irq_data & OMAP_RTC_STATUS_ALARM) {
+               rtc->type->unlock(rtc);
                rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM);
+               rtc->type->lock(rtc);
                events |= RTC_IRQF | RTC_AF;
        }
 
@@ -218,9 +243,11 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
                irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
        }
        rtc_wait_not_busy(rtc);
+       rtc->type->unlock(rtc);
        rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
        if (rtc->type->has_irqwakeen)
                rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
+       rtc->type->lock(rtc);
        local_irq_enable();
 
        return 0;
@@ -293,12 +320,14 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
        local_irq_disable();
        rtc_wait_not_busy(rtc);
 
+       rtc->type->unlock(rtc);
        rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year);
        rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon);
        rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday);
        rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour);
        rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min);
        rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec);
+       rtc->type->lock(rtc);
 
        local_irq_enable();
 
@@ -341,6 +370,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        local_irq_disable();
        rtc_wait_not_busy(rtc);
 
+       rtc->type->unlock(rtc);
        rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year);
        rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon);
        rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday);
@@ -362,6 +392,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
        if (rtc->type->has_irqwakeen)
                rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
+       rtc->type->lock(rtc);
 
        local_irq_enable();
 
@@ -391,6 +422,7 @@ static void omap_rtc_power_off(void)
        unsigned long now;
        u32 val;
 
+       rtc->type->unlock(rtc);
        /* enable pmic_power_en control */
        val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
        rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);
@@ -423,6 +455,7 @@ static void omap_rtc_power_off(void)
        val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
        rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG,
                        val | OMAP_RTC_INTERRUPTS_IT_ALARM2);
+       rtc->type->lock(rtc);
 
        /*
         * Wait for alarm to trigger (within two seconds) and external PMIC to
@@ -442,17 +475,21 @@ static struct rtc_class_ops omap_rtc_ops = {
 
 static const struct omap_rtc_device_type omap_rtc_default_type = {
        .has_power_up_reset = true,
+       .lock           = default_rtc_lock,
+       .unlock         = default_rtc_unlock,
 };
 
 static const struct omap_rtc_device_type omap_rtc_am3352_type = {
        .has_32kclk_en  = true,
-       .has_kicker     = true,
        .has_irqwakeen  = true,
        .has_pmic_mode  = true,
+       .lock           = am3352_rtc_lock,
+       .unlock         = am3352_rtc_unlock,
 };
 
 static const struct omap_rtc_device_type omap_rtc_da830_type = {
-       .has_kicker     = true,
+       .lock           = am3352_rtc_lock,
+       .unlock         = am3352_rtc_unlock,
 };
 
 static const struct platform_device_id omap_rtc_id_table[] = {
@@ -484,7 +521,7 @@ static const struct of_device_id omap_rtc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 
-static int __init omap_rtc_probe(struct platform_device *pdev)
+static int omap_rtc_probe(struct platform_device *pdev)
 {
        struct omap_rtc *rtc;
        struct resource *res;
@@ -527,10 +564,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
 
-       if (rtc->type->has_kicker) {
-               rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE);
-               rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE);
-       }
+       rtc->type->unlock(rtc);
 
        /*
         * disable interrupts
@@ -593,6 +627,8 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        if (reg != new_ctrl)
                rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl);
 
+       rtc->type->lock(rtc);
+
        device_init_wakeup(&pdev->dev, true);
 
        rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
@@ -626,8 +662,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 
 err:
        device_init_wakeup(&pdev->dev, false);
-       if (rtc->type->has_kicker)
-               rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0);
+       rtc->type->lock(rtc);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
@@ -646,11 +681,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 0);
 
+       rtc->type->unlock(rtc);
        /* leave rtc running, but disable irqs */
        rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
 
-       if (rtc->type->has_kicker)
-               rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0);
+       rtc->type->lock(rtc);
 
        /* Disable the clock/module */
        pm_runtime_put_sync(&pdev->dev);
@@ -666,6 +701,7 @@ static int omap_rtc_suspend(struct device *dev)
 
        rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
 
+       rtc->type->unlock(rtc);
        /*
         * FIXME: the RTC alarm is not currently acting as a wakeup event
         * source on some platforms, and in fact this enable() call is just
@@ -675,6 +711,7 @@ static int omap_rtc_suspend(struct device *dev)
                enable_irq_wake(rtc->irq_alarm);
        else
                rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
+       rtc->type->lock(rtc);
 
        /* Disable the clock/module */
        pm_runtime_put_sync(dev);
@@ -689,10 +726,12 @@ static int omap_rtc_resume(struct device *dev)
        /* Enable the clock/module so that we can access the registers */
        pm_runtime_get_sync(dev);
 
+       rtc->type->unlock(rtc);
        if (device_may_wakeup(dev))
                disable_irq_wake(rtc->irq_alarm);
        else
                rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg);
+       rtc->type->lock(rtc);
 
        return 0;
 }
@@ -709,12 +748,15 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
         * Keep the ALARM interrupt enabled to allow the system to power up on
         * alarm events.
         */
+       rtc->type->unlock(rtc);
        mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
        mask &= OMAP_RTC_INTERRUPTS_IT_ALARM;
        rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask);
+       rtc->type->lock(rtc);
 }
 
 static struct platform_driver omap_rtc_driver = {
+       .probe          = omap_rtc_probe,
        .remove         = __exit_p(omap_rtc_remove),
        .shutdown       = omap_rtc_shutdown,
        .driver         = {
@@ -725,7 +767,7 @@ static struct platform_driver omap_rtc_driver = {
        .id_table       = omap_rtc_id_table,
 };
 
-module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
+module_platform_driver(omap_rtc_driver);
 
 MODULE_ALIAS("platform:omap_rtc");
 MODULE_AUTHOR("George G. Davis (and others)");
index 95f6521..7061dca 100644 (file)
@@ -16,8 +16,9 @@
  * along with this program.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRVNAME                "rtc-opal"
-#define pr_fmt(fmt)    DRVNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/err.h>
index 96fb32e..0ba7e59 100644 (file)
@@ -246,7 +246,6 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
        struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
-       int err;
        unsigned char buf[9];
 
        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
@@ -272,12 +271,8 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
 
-       err = pcf8563_write_block_data(client, PCF8563_REG_SC,
+       return pcf8563_write_block_data(client, PCF8563_REG_SC,
                                9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
-       if (err)
-               return err;
-
-       return 0;
 }
 
 #ifdef CONFIG_RTC_INTF_DEV
index f4cf685..76cbad7 100644 (file)
@@ -39,7 +39,6 @@ struct s3c_rtc {
        void __iomem *base;
        struct clk *rtc_clk;
        struct clk *rtc_src_clk;
-       bool enabled;
 
        struct s3c_rtc_data *data;
 
@@ -67,26 +66,25 @@ struct s3c_rtc_data {
        void (*disable) (struct s3c_rtc *info);
 };
 
-static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
+static void s3c_rtc_enable_clk(struct s3c_rtc *info)
 {
        unsigned long irq_flags;
 
        spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
-       if (enable) {
-               if (!info->enabled) {
-                       clk_enable(info->rtc_clk);
-                       if (info->data->needs_src_clk)
-                               clk_enable(info->rtc_src_clk);
-                       info->enabled = true;
-               }
-       } else {
-               if (info->enabled) {
-                       if (info->data->needs_src_clk)
-                               clk_disable(info->rtc_src_clk);
-                       clk_disable(info->rtc_clk);
-                       info->enabled = false;
-               }
-       }
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+       spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
+}
+
+static void s3c_rtc_disable_clk(struct s3c_rtc *info)
+{
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
        spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
 }
 
@@ -119,20 +117,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
 
        dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
+
        tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
 
        if (enabled)
                tmp |= S3C2410_RTCALM_ALMEN;
 
        writeb(tmp, info->base + S3C2410_RTCALM);
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
 
-       s3c_rtc_alarm_clk_enable(info, enabled);
+       s3c_rtc_disable_clk(info);
 
        return 0;
 }
@@ -143,18 +137,12 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
        if (!is_power_of_2(freq))
                return -EINVAL;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
        spin_lock_irq(&info->pie_lock);
 
        if (info->data->set_freq)
                info->data->set_freq(info, freq);
 
        spin_unlock_irq(&info->pie_lock);
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
 
        return 0;
 }
@@ -165,9 +153,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
        struct s3c_rtc *info = dev_get_drvdata(dev);
        unsigned int have_retried = 0;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
 
  retry_get_time:
        rtc_tm->tm_min  = readb(info->base + S3C2410_RTCMIN);
@@ -194,6 +180,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
        rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
        rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
+       s3c_rtc_disable_clk(info);
+
        rtc_tm->tm_year += 100;
 
        dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
@@ -202,10 +190,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 
        rtc_tm->tm_mon -= 1;
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
        return rtc_valid_tm(rtc_tm);
 }
 
@@ -225,9 +209,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
 
        writeb(bin2bcd(tm->tm_sec),  info->base + S3C2410_RTCSEC);
        writeb(bin2bcd(tm->tm_min),  info->base + S3C2410_RTCMIN);
@@ -236,9 +218,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
        writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
        writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
+       s3c_rtc_disable_clk(info);
 
        return 0;
 }
@@ -249,9 +229,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_time *alm_tm = &alrm->time;
        unsigned int alm_en;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
 
        alm_tm->tm_sec  = readb(info->base + S3C2410_ALMSEC);
        alm_tm->tm_min  = readb(info->base + S3C2410_ALMMIN);
@@ -262,6 +240,8 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        alm_en = readb(info->base + S3C2410_RTCALM);
 
+       s3c_rtc_disable_clk(info);
+
        alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
 
        dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",
@@ -269,9 +249,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
                 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
                 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
 
-
        /* decode the alarm enable field */
-
        if (alm_en & S3C2410_RTCALM_SECEN)
                alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
        else
@@ -304,10 +282,6 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
        else
                alm_tm->tm_year = -1;
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
        return 0;
 }
 
@@ -317,15 +291,13 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_time *tm = &alrm->time;
        unsigned int alrm_en;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
-
        dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
                 alrm->enabled,
                 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
                 tm->tm_hour, tm->tm_min, tm->tm_sec);
 
+       s3c_rtc_enable_clk(info);
+
        alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
        writeb(0x00, info->base + S3C2410_RTCALM);
 
@@ -348,11 +320,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        writeb(alrm_en, info->base + S3C2410_RTCALM);
 
-       s3c_rtc_setaie(dev, alrm->enabled);
+       s3c_rtc_disable_clk(info);
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
+       s3c_rtc_setaie(dev, alrm->enabled);
 
        return 0;
 }
@@ -361,16 +331,12 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
        struct s3c_rtc *info = dev_get_drvdata(dev);
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
 
        if (info->data->enable_tick)
                info->data->enable_tick(info, seq);
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
+       s3c_rtc_disable_clk(info);
 
        return 0;
 }
@@ -388,10 +354,6 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
 {
        unsigned int con, tmp;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
-
        con = readw(info->base + S3C2410_RTCCON);
        /* re-enable the device, and check it is ok */
        if ((con & S3C2410_RTCCON_RTCEN) == 0) {
@@ -417,20 +379,12 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
                writew(tmp & ~S3C2410_RTCCON_CLKRST,
                        info->base + S3C2410_RTCCON);
        }
-
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
 }
 
 static void s3c24xx_rtc_disable(struct s3c_rtc *info)
 {
        unsigned int con;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
-
        con = readw(info->base + S3C2410_RTCCON);
        con &= ~S3C2410_RTCCON_RTCEN;
        writew(con, info->base + S3C2410_RTCCON);
@@ -438,28 +392,16 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info)
        con = readb(info->base + S3C2410_TICNT);
        con &= ~S3C2410_TICNT_ENABLE;
        writeb(con, info->base + S3C2410_TICNT);
-
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
 }
 
 static void s3c6410_rtc_disable(struct s3c_rtc *info)
 {
        unsigned int con;
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
-
        con = readw(info->base + S3C2410_RTCCON);
        con &= ~S3C64XX_RTCCON_TICEN;
        con &= ~S3C2410_RTCCON_RTCEN;
        writew(con, info->base + S3C2410_RTCCON);
-
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
 }
 
 static int s3c_rtc_remove(struct platform_device *pdev)
@@ -554,6 +496,20 @@ static int s3c_rtc_probe(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 1);
 
+       /* Check RTC Time */
+       if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) {
+               rtc_tm.tm_year  = 100;
+               rtc_tm.tm_mon   = 0;
+               rtc_tm.tm_mday  = 1;
+               rtc_tm.tm_hour  = 0;
+               rtc_tm.tm_min   = 0;
+               rtc_tm.tm_sec   = 0;
+
+               s3c_rtc_settime(&pdev->dev, &rtc_tm);
+
+               dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
+       }
+
        /* register RTC and exit */
        info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
                                  THIS_MODULE);
@@ -577,36 +533,21 @@ static int s3c_rtc_probe(struct platform_device *pdev)
                goto err_nortc;
        }
 
-       /* Check RTC Time */
-       s3c_rtc_gettime(&pdev->dev, &rtc_tm);
-
-       if (rtc_valid_tm(&rtc_tm)) {
-               rtc_tm.tm_year  = 100;
-               rtc_tm.tm_mon   = 0;
-               rtc_tm.tm_mday  = 1;
-               rtc_tm.tm_hour  = 0;
-               rtc_tm.tm_min   = 0;
-               rtc_tm.tm_sec   = 0;
-
-               s3c_rtc_settime(&pdev->dev, &rtc_tm);
-
-               dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
-       }
-
        if (info->data->select_tick_clk)
                info->data->select_tick_clk(info);
 
        s3c_rtc_setfreq(info, 1);
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
+       s3c_rtc_disable_clk(info);
 
        return 0;
 
  err_nortc:
        if (info->data->disable)
                info->data->disable(info);
+
+       if (info->data->needs_src_clk)
+               clk_disable_unprepare(info->rtc_src_clk);
        clk_disable_unprepare(info->rtc_clk);
 
        return ret;
@@ -618,9 +559,7 @@ static int s3c_rtc_suspend(struct device *dev)
 {
        struct s3c_rtc *info = dev_get_drvdata(dev);
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
+       s3c_rtc_enable_clk(info);
 
        /* save TICNT for anyone using periodic interrupts */
        if (info->data->save_tick_cnt)
@@ -636,10 +575,6 @@ static int s3c_rtc_suspend(struct device *dev)
                        dev_err(dev, "enable_irq_wake failed\n");
        }
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
        return 0;
 }
 
@@ -647,25 +582,19 @@ static int s3c_rtc_resume(struct device *dev)
 {
        struct s3c_rtc *info = dev_get_drvdata(dev);
 
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
-
        if (info->data->enable)
                info->data->enable(info);
 
        if (info->data->restore_tick_cnt)
                info->data->restore_tick_cnt(info);
 
+       s3c_rtc_disable_clk(info);
+
        if (device_may_wakeup(dev) && info->wake_en) {
                disable_irq_wake(info->irq_alarm);
                info->wake_en = false;
        }
 
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
        return 0;
 }
 #endif
@@ -673,29 +602,13 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
 
 static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
 {
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
        rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
-       s3c_rtc_alarm_clk_enable(info, false);
 }
 
 static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
 {
-       clk_enable(info->rtc_clk);
-       if (info->data->needs_src_clk)
-               clk_enable(info->rtc_src_clk);
        rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
        writeb(mask, info->base + S3C2410_INTP);
-       if (info->data->needs_src_clk)
-               clk_disable(info->rtc_src_clk);
-       clk_disable(info->rtc_clk);
-
-       s3c_rtc_alarm_clk_enable(info, false);
 }
 
 static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq)
index 4008b84..8c70d78 100644 (file)
@@ -15,6 +15,8 @@
  *  GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
@@ -90,7 +92,7 @@ struct s5m_rtc_info {
        struct regmap *regmap;
        struct rtc_device *rtc_dev;
        int irq;
-       int device_type;
+       enum sec_device_type device_type;
        int rtc_24hr_mode;
        const struct s5m_rtc_reg_config *regs;
 };
@@ -146,7 +148,7 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
        data[RTC_YEAR1] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
 
        if (tm->tm_year < 100) {
-               pr_err("s5m8767 RTC cannot handle the year %d.\n",
+               pr_err("RTC cannot handle the year %d\n",
                       1900 + tm->tm_year);
                return -EINVAL;
        } else {
@@ -187,6 +189,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
                val &= S5M_ALARM0_STATUS;
                break;
        case S2MPS14X:
+       case S2MPS13X:
                ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2,
                                &val);
                val &= S2MPS_ALARM0_STATUS;
@@ -252,6 +255,9 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
        case S2MPS14X:
                data |= S2MPS_RTC_RUDR_MASK;
                break;
+       case S2MPS13X:
+               data |= S2MPS13_RTC_AUDR_MASK;
+               break;
        default:
                return -EINVAL;
        }
@@ -265,6 +271,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 
        ret = s5m8767_wait_for_udr_update(info);
 
+       /* On S2MPS13 the AUDR is not auto-cleared */
+       if (info->device_type == S2MPS13X)
+               regmap_update_bits(info->regmap, info->regs->rtc_udr_update,
+                                  S2MPS13_RTC_AUDR_MASK, 0);
+
        return ret;
 }
 
@@ -306,7 +317,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
        u8 data[info->regs->regs_count];
        int ret;
 
-       if (info->device_type == S2MPS14X) {
+       if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) {
                ret = regmap_update_bits(info->regmap,
                                info->regs->rtc_udr_update,
                                S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
@@ -329,6 +340,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode);
                break;
 
@@ -355,6 +367,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
                break;
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                ret = s5m8767_tm_to_data(tm, data);
                break;
        default:
@@ -402,6 +415,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
                alrm->enabled = 0;
                for (i = 0; i < info->regs->regs_count; i++) {
@@ -450,6 +464,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
 
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                for (i = 0; i < info->regs->regs_count; i++)
                        data[i] &= ~ALARM_ENABLE_MASK;
 
@@ -494,6 +509,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
 
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                data[RTC_SEC] |= ALARM_ENABLE_MASK;
                data[RTC_MIN] |= ALARM_ENABLE_MASK;
                data[RTC_HOUR] |= ALARM_ENABLE_MASK;
@@ -533,6 +549,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        case S5M8767X:
        case S2MPS14X:
+       case S2MPS13X:
                s5m8767_tm_to_data(&alrm->time, data);
                break;
 
@@ -615,6 +632,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
                break;
 
        case S2MPS14X:
+       case S2MPS13X:
                data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
                ret = regmap_write(info->regmap, info->regs->ctrl, data[0]);
                break;
@@ -650,8 +668,9 @@ static int s5m_rtc_probe(struct platform_device *pdev)
        if (!info)
                return -ENOMEM;
 
-       switch (pdata->device_type) {
+       switch (platform_get_device_id(pdev)->driver_data) {
        case S2MPS14X:
+       case S2MPS13X:
                regmap_cfg = &s2mps14_rtc_regmap_config;
                info->regs = &s2mps_rtc_regs;
                alarm_irq = S2MPS14_IRQ_RTCA0;
@@ -667,7 +686,9 @@ static int s5m_rtc_probe(struct platform_device *pdev)
                alarm_irq = S5M8767_IRQ_RTCA1;
                break;
        default:
-               dev_err(&pdev->dev, "Device type is not supported by RTC driver\n");
+               dev_err(&pdev->dev,
+                               "Device type %lu is not supported by RTC driver\n",
+                               platform_get_device_id(pdev)->driver_data);
                return -ENODEV;
        }
 
@@ -687,7 +708,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
        info->dev = &pdev->dev;
        info->s5m87xx = s5m87xx;
-       info->device_type = s5m87xx->device_type;
+       info->device_type = platform_get_device_id(pdev)->driver_data;
 
        if (s5m87xx->irq_data) {
                info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
@@ -772,6 +793,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
 
 static const struct platform_device_id s5m_rtc_id[] = {
        { "s5m-rtc",            S5M8767X },
+       { "s2mps13-rtc",        S2MPS13X },
        { "s2mps14-rtc",        S2MPS14X },
        { },
 };
index 2939cdc..eb09edd 100644 (file)
@@ -42,6 +42,8 @@
 #define STMP3XXX_RTC_STAT                      0x10
 #define STMP3XXX_RTC_STAT_STALE_SHIFT          16
 #define STMP3XXX_RTC_STAT_RTC_PRESENT          0x80000000
+#define STMP3XXX_RTC_STAT_XTAL32000_PRESENT    0x10000000
+#define STMP3XXX_RTC_STAT_XTAL32768_PRESENT    0x08000000
 
 #define STMP3XXX_RTC_SECONDS                   0x30
 
 #define STMP3XXX_RTC_PERSISTENT0               0x60
 #define STMP3XXX_RTC_PERSISTENT0_SET           0x64
 #define STMP3XXX_RTC_PERSISTENT0_CLR           0x68
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN      0x00000004
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE    0x00000080
+#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE           (1 << 0)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN         (1 << 1)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN              (1 << 2)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP       (1 << 4)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP       (1 << 5)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ           (1 << 6)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE            (1 << 7)
 
 #define STMP3XXX_RTC_PERSISTENT1               0x70
 /* missing bitmask in headers */
@@ -248,6 +254,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 {
        struct stmp3xxx_rtc_data *rtc_data;
        struct resource *r;
+       u32 rtc_stat;
+       u32 pers0_set, pers0_clr;
+       u32 crystalfreq = 0;
        int err;
 
        rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL);
@@ -268,8 +277,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
        rtc_data->irq_alarm = platform_get_irq(pdev, 0);
 
-       if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
-                       STMP3XXX_RTC_STAT_RTC_PRESENT)) {
+       rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT);
+       if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) {
                dev_err(&pdev->dev, "no device onboard\n");
                return -ENODEV;
        }
@@ -282,9 +291,54 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
                return err;
        }
 
+       /*
+        * Obviously the rtc needs a clock input to be able to run.
+        * This clock can be provided by an external 32k crystal. If that one is
+        * missing XTAL must not be disabled in suspend which consumes a
+        * lot of power. Normally the presence and exact frequency (supported
+        * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality
+        * proves these fuses are not blown correctly on all machines, so the
+        * frequency can be overridden in the device tree.
+        */
+       if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT)
+               crystalfreq = 32000;
+       else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT)
+               crystalfreq = 32768;
+
+       of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq",
+                            &crystalfreq);
+
+       switch (crystalfreq) {
+       case 32000:
+               /* keep 32kHz crystal running in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ |
+                       STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
+               break;
+       case 32768:
+               /* keep 32.768kHz crystal running in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ;
+               break;
+       default:
+               dev_warn(&pdev->dev,
+                        "invalid crystal-freq specified in device-tree. Assuming no crystal\n");
+               /* fall-through */
+       case 0:
+               /* keep XTAL on in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+       }
+
+       writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+
        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
-                       STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+                       STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
                        rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 
        writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
index 5baea3f..2dc787d 100644 (file)
@@ -18,6 +18,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -145,8 +147,7 @@ static int twl_rtc_read_u8(u8 *data, u8 reg)
 
        ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
        if (ret < 0)
-               pr_err("twl_rtc: Could not read TWL"
-                      "register %X - error %d\n", reg, ret);
+               pr_err("Could not read TWL register %X - error %d\n", reg, ret);
        return ret;
 }
 
@@ -159,8 +160,8 @@ static int twl_rtc_write_u8(u8 data, u8 reg)
 
        ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
        if (ret < 0)
-               pr_err("twl_rtc: Could not write TWL"
-                      "register %X - error %d\n", reg, ret);
+               pr_err("Could not write TWL register %X - error %d\n",
+                      reg, ret);
        return ret;
 }
 
index b1de58e..5638b7b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/rtc.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #define DRV_VERSION "1.0.8"
 
@@ -366,8 +367,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
         * perform sign extension. The formula is
         * Catr = (atr * 0.25pF) + 11.00pF.
         */
-       if (atr & 0x20)
-               atr |= 0xC0;
+       atr = sign_extend32(atr, 5);
 
        dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr);
 
index e90a374..cc3b9d3 100644 (file)
@@ -1079,22 +1079,18 @@ bfad_start_ops(struct bfad_s *bfad) {
 int
 bfad_worker(void *ptr)
 {
-       struct bfad_s *bfad;
-       unsigned long   flags;
-
-       bfad = (struct bfad_s *)ptr;
-
-       while (!kthread_should_stop()) {
+       struct bfad_s *bfad = ptr;
+       unsigned long flags;
 
-               /* Send event BFAD_E_INIT_SUCCESS */
-               bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
+       if (kthread_should_stop())
+               return 0;
 
-               spin_lock_irqsave(&bfad->bfad_lock, flags);
-               bfad->bfad_tsk = NULL;
-               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       /* Send event BFAD_E_INIT_SUCCESS */
+       bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
 
-               break;
-       }
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfad->bfad_tsk = NULL;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
        return 0;
 }
index cf38e15..08d90e2 100644 (file)
@@ -86,6 +86,7 @@ int main(int argc, char **argv)
                case 'j':
                        include_jump = 1;
                        break;
+               default:
                        return usage();
                }
        }
index f2ba88a..82d14cd 100644 (file)
@@ -61,6 +61,7 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct
                        kcalloc(size, sizeof(struct buffer_head *),
                                GFP_KERNEL);
                if (!bh_fplus) {
+                       ret = -ENOMEM;
                        adfs_error(sb, "not enough memory for"
                                        " dir object %X (%d blocks)", id, size);
                        goto out;
index 9852bdf..a19c31d 100644 (file)
@@ -316,7 +316,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
        dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL);
        if (dm == NULL) {
                adfs_error(sb, "not enough memory");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        for (zone = 0; zone < nzones; zone++, map_addr++) {
@@ -349,7 +349,7 @@ error_free:
                brelse(dm[zone].dm_bh);
 
        kfree(dm);
-       return NULL;
+       return ERR_PTR(-EIO);
 }
 
 static inline unsigned long adfs_discsize(struct adfs_discrecord *dr, int block_bits)
@@ -370,6 +370,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
        unsigned char *b_data;
        struct adfs_sb_info *asb;
        struct inode *root;
+       int ret = -EINVAL;
 
        sb->s_flags |= MS_NODIRATIME;
 
@@ -391,6 +392,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
        sb_set_blocksize(sb, BLOCK_SIZE);
        if (!(bh = sb_bread(sb, ADFS_DISCRECORD / BLOCK_SIZE))) {
                adfs_error(sb, "unable to read superblock");
+               ret = -EIO;
                goto error;
        }
 
@@ -400,6 +402,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                if (!silent)
                        printk("VFS: Can't find an adfs filesystem on dev "
                                "%s.\n", sb->s_id);
+               ret = -EINVAL;
                goto error_free_bh;
        }
 
@@ -412,6 +415,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                if (!silent)
                        printk("VPS: Can't find an adfs filesystem on dev "
                                "%s.\n", sb->s_id);
+               ret = -EINVAL;
                goto error_free_bh;
        }
 
@@ -421,11 +425,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                if (!bh) {
                        adfs_error(sb, "couldn't read superblock on "
                                "2nd try.");
+                       ret = -EIO;
                        goto error;
                }
                b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
                if (adfs_checkbblk(b_data)) {
                        adfs_error(sb, "disc record mismatch, very weird!");
+                       ret = -EINVAL;
                        goto error_free_bh;
                }
                dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
@@ -433,6 +439,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                if (!silent)
                        printk(KERN_ERR "VFS: Unsupported blocksize on dev "
                                "%s.\n", sb->s_id);
+               ret = -EINVAL;
                goto error;
        }
 
@@ -447,10 +454,12 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
        asb->s_size             = adfs_discsize(dr, sb->s_blocksize_bits);
        asb->s_version          = dr->format_version;
        asb->s_log2sharesize    = dr->log2sharesize;
-       
+
        asb->s_map = adfs_read_map(sb, dr);
-       if (!asb->s_map)
+       if (IS_ERR(asb->s_map)) {
+               ret =  PTR_ERR(asb->s_map);
                goto error_free_bh;
+       }
 
        brelse(bh);
 
@@ -499,6 +508,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
                        brelse(asb->s_map[i].dm_bh);
                kfree(asb->s_map);
                adfs_error(sb, "get root inode failed\n");
+               ret = -EIO;
                goto error;
        }
        return 0;
@@ -508,7 +518,7 @@ error_free_bh:
 error:
        sb->s_fs_info = NULL;
        kfree(asb);
-       return -EINVAL;
+       return ret;
 }
 
 static struct dentry *adfs_mount(struct file_system_type *fs_type,
index c8764bd..cffe837 100644 (file)
@@ -106,18 +106,22 @@ struct affs_sb_info {
        spinlock_t work_lock;           /* protects sb_work and work_queued */
 };
 
-#define SF_INTL                0x0001          /* International filesystem. */
-#define SF_BM_VALID    0x0002          /* Bitmap is valid. */
-#define SF_IMMUTABLE   0x0004          /* Protection bits cannot be changed */
-#define SF_QUIET       0x0008          /* chmod errors will be not reported */
-#define SF_SETUID      0x0010          /* Ignore Amiga uid */
-#define SF_SETGID      0x0020          /* Ignore Amiga gid */
-#define SF_SETMODE     0x0040          /* Ignore Amiga protection bits */
-#define SF_MUFS                0x0100          /* Use MUFS uid/gid mapping */
-#define SF_OFS         0x0200          /* Old filesystem */
-#define SF_PREFIX      0x0400          /* Buffer for prefix is allocated */
-#define SF_VERBOSE     0x0800          /* Talk about fs when mounting */
-#define SF_NO_TRUNCATE 0x1000          /* Don't truncate filenames */
+#define AFFS_MOUNT_SF_INTL             0x0001 /* International filesystem. */
+#define AFFS_MOUNT_SF_BM_VALID         0x0002 /* Bitmap is valid. */
+#define AFFS_MOUNT_SF_IMMUTABLE                0x0004 /* Protection bits cannot be changed */
+#define AFFS_MOUNT_SF_QUIET            0x0008 /* chmod errors will be not reported */
+#define AFFS_MOUNT_SF_SETUID           0x0010 /* Ignore Amiga uid */
+#define AFFS_MOUNT_SF_SETGID           0x0020 /* Ignore Amiga gid */
+#define AFFS_MOUNT_SF_SETMODE          0x0040 /* Ignore Amiga protection bits */
+#define AFFS_MOUNT_SF_MUFS             0x0100 /* Use MUFS uid/gid mapping */
+#define AFFS_MOUNT_SF_OFS              0x0200 /* Old filesystem */
+#define AFFS_MOUNT_SF_PREFIX           0x0400 /* Buffer for prefix is allocated */
+#define AFFS_MOUNT_SF_VERBOSE          0x0800 /* Talk about fs when mounting */
+#define AFFS_MOUNT_SF_NO_TRUNCATE      0x1000 /* Don't truncate filenames */
+
+#define affs_clear_opt(o, opt)    (o &= ~AFFS_MOUNT_##opt)
+#define affs_set_opt(o, opt)      (o |= AFFS_MOUNT_##opt)
+#define affs_test_opt(o, opt)     ((o) & AFFS_MOUNT_##opt)
 
 /* short cut to get to the affs specific sb data */
 static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
index 388da1e..5022ac9 100644 (file)
@@ -472,7 +472,8 @@ bool
 affs_nofilenametruncate(const struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
-       return AFFS_SB(inode->i_sb)->s_flags & SF_NO_TRUNCATE;
+
+       return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE);
 
 }
 
index dcf2795..659c579 100644 (file)
@@ -914,7 +914,7 @@ affs_truncate(struct inode *inode)
        if (inode->i_size) {
                AFFS_I(inode)->i_blkcnt = last_blk + 1;
                AFFS_I(inode)->i_extcnt = ext + 1;
-               if (AFFS_SB(sb)->s_flags & SF_OFS) {
+               if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS)) {
                        struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
                        u32 tmp;
                        if (IS_ERR(bh)) {
index 6f34510..9628003 100644 (file)
@@ -66,23 +66,23 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
        AFFS_I(inode)->i_lastalloc = 0;
        AFFS_I(inode)->i_pa_cnt = 0;
 
-       if (sbi->s_flags & SF_SETMODE)
+       if (affs_test_opt(sbi->s_flags, SF_SETMODE))
                inode->i_mode = sbi->s_mode;
        else
                inode->i_mode = prot_to_mode(prot);
 
        id = be16_to_cpu(tail->uid);
-       if (id == 0 || sbi->s_flags & SF_SETUID)
+       if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID))
                inode->i_uid = sbi->s_uid;
-       else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
+       else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
                i_uid_write(inode, 0);
        else
                i_uid_write(inode, id);
 
        id = be16_to_cpu(tail->gid);
-       if (id == 0 || sbi->s_flags & SF_SETGID)
+       if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID))
                inode->i_gid = sbi->s_gid;
-       else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
+       else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
                i_gid_write(inode, 0);
        else
                i_gid_write(inode, id);
@@ -94,7 +94,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                /* fall through */
        case ST_USERDIR:
                if (be32_to_cpu(tail->stype) == ST_USERDIR ||
-                   sbi->s_flags & SF_SETMODE) {
+                   affs_test_opt(sbi->s_flags, SF_SETMODE)) {
                        if (inode->i_mode & S_IRUSR)
                                inode->i_mode |= S_IXUSR;
                        if (inode->i_mode & S_IRGRP)
@@ -133,7 +133,8 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                }
                if (tail->link_chain)
                        set_nlink(inode, 2);
-               inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
+               inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ?
+                                         &affs_aops_ofs : &affs_aops;
                inode->i_op = &affs_file_inode_operations;
                inode->i_fop = &affs_file_operations;
                break;
@@ -190,15 +191,15 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc)
                if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
                        uid = i_uid_read(inode);
                        gid = i_gid_read(inode);
-                       if (AFFS_SB(sb)->s_flags & SF_MUFS) {
+                       if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) {
                                if (uid == 0 || uid == 0xFFFF)
                                        uid = uid ^ ~0;
                                if (gid == 0 || gid == 0xFFFF)
                                        gid = gid ^ ~0;
                        }
-                       if (!(AFFS_SB(sb)->s_flags & SF_SETUID))
+                       if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID))
                                tail->uid = cpu_to_be16(uid);
-                       if (!(AFFS_SB(sb)->s_flags & SF_SETGID))
+                       if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID))
                                tail->gid = cpu_to_be16(gid);
                }
        }
@@ -221,11 +222,14 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
        if (error)
                goto out;
 
-       if (((attr->ia_valid & ATTR_UID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETUID)) ||
-           ((attr->ia_valid & ATTR_GID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETGID)) ||
+       if (((attr->ia_valid & ATTR_UID) &&
+             affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) ||
+           ((attr->ia_valid & ATTR_GID) &&
+             affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) ||
            ((attr->ia_valid & ATTR_MODE) &&
-            (AFFS_SB(inode->i_sb)->s_flags & (SF_SETMODE | SF_IMMUTABLE)))) {
-               if (!(AFFS_SB(inode->i_sb)->s_flags & SF_QUIET))
+            (AFFS_SB(inode->i_sb)->s_flags &
+             (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) {
+               if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET))
                        error = -EPERM;
                goto out;
        }
index ffb7bd8..ec8ca0e 100644 (file)
@@ -53,7 +53,8 @@ affs_intl_toupper(int ch)
 static inline toupper_t
 affs_get_toupper(struct super_block *sb)
 {
-       return AFFS_SB(sb)->s_flags & SF_INTL ? affs_intl_toupper : affs_toupper;
+       return affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL) ?
+              affs_intl_toupper : affs_toupper;
 }
 
 /*
@@ -275,7 +276,8 @@ affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 
        inode->i_op = &affs_file_inode_operations;
        inode->i_fop = &affs_file_operations;
-       inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
+       inode->i_mapping->a_ops = affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS) ?
+                                 &affs_aops_ofs : &affs_aops;
        error = affs_add_entry(dir, inode, dentry, ST_FILE);
        if (error) {
                clear_nlink(inode);
index 4cf0e91..3f89c9e 100644 (file)
@@ -227,22 +227,22 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
                        if (match_octal(&args[0], &option))
                                return 0;
                        *mode = option & 0777;
-                       *mount_opts |= SF_SETMODE;
+                       affs_set_opt(*mount_opts, SF_SETMODE);
                        break;
                case Opt_mufs:
-                       *mount_opts |= SF_MUFS;
+                       affs_set_opt(*mount_opts, SF_MUFS);
                        break;
                case Opt_notruncate:
-                       *mount_opts |= SF_NO_TRUNCATE;
+                       affs_set_opt(*mount_opts, SF_NO_TRUNCATE);
                        break;
                case Opt_prefix:
                        *prefix = match_strdup(&args[0]);
                        if (!*prefix)
                                return 0;
-                       *mount_opts |= SF_PREFIX;
+                       affs_set_opt(*mount_opts, SF_PREFIX);
                        break;
                case Opt_protect:
-                       *mount_opts |= SF_IMMUTABLE;
+                       affs_set_opt(*mount_opts, SF_IMMUTABLE);
                        break;
                case Opt_reserved:
                        if (match_int(&args[0], reserved))
@@ -258,7 +258,7 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
                        *gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(*gid))
                                return 0;
-                       *mount_opts |= SF_SETGID;
+                       affs_set_opt(*mount_opts, SF_SETGID);
                        break;
                case Opt_setuid:
                        if (match_int(&args[0], &option))
@@ -266,10 +266,10 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
                        *uid = make_kuid(current_user_ns(), option);
                        if (!uid_valid(*uid))
                                return 0;
-                       *mount_opts |= SF_SETUID;
+                       affs_set_opt(*mount_opts, SF_SETUID);
                        break;
                case Opt_verbose:
-                       *mount_opts |= SF_VERBOSE;
+                       affs_set_opt(*mount_opts, SF_VERBOSE);
                        break;
                case Opt_volume: {
                        char *vol = match_strdup(&args[0]);
@@ -435,30 +435,31 @@ got_root:
        case MUFS_FS:
        case MUFS_INTLFFS:
        case MUFS_DCFFS:
-               sbi->s_flags |= SF_MUFS;
+               affs_set_opt(sbi->s_flags, SF_MUFS);
                /* fall thru */
        case FS_INTLFFS:
        case FS_DCFFS:
-               sbi->s_flags |= SF_INTL;
+               affs_set_opt(sbi->s_flags, SF_INTL);
                break;
        case MUFS_FFS:
-               sbi->s_flags |= SF_MUFS;
+               affs_set_opt(sbi->s_flags, SF_MUFS);
                break;
        case FS_FFS:
                break;
        case MUFS_OFS:
-               sbi->s_flags |= SF_MUFS;
+               affs_set_opt(sbi->s_flags, SF_MUFS);
                /* fall thru */
        case FS_OFS:
-               sbi->s_flags |= SF_OFS;
+               affs_set_opt(sbi->s_flags, SF_OFS);
                sb->s_flags |= MS_NOEXEC;
                break;
        case MUFS_DCOFS:
        case MUFS_INTLOFS:
-               sbi->s_flags |= SF_MUFS;
+               affs_set_opt(sbi->s_flags, SF_MUFS);
        case FS_DCOFS:
        case FS_INTLOFS:
-               sbi->s_flags |= SF_INTL | SF_OFS;
+               affs_set_opt(sbi->s_flags, SF_INTL);
+               affs_set_opt(sbi->s_flags, SF_OFS);
                sb->s_flags |= MS_NOEXEC;
                break;
        default:
@@ -467,7 +468,7 @@ got_root:
                return -EINVAL;
        }
 
-       if (mount_flags & SF_VERBOSE) {
+       if (affs_test_opt(mount_flags, SF_VERBOSE)) {
                u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
                pr_notice("Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
                        len > 31 ? 31 : len,
@@ -478,7 +479,7 @@ got_root:
        sb->s_flags |= MS_NODEV | MS_NOSUID;
 
        sbi->s_data_blksize = sb->s_blocksize;
-       if (sbi->s_flags & SF_OFS)
+       if (affs_test_opt(sbi->s_flags, SF_OFS))
                sbi->s_data_blksize -= 24;
 
        tmp_flags = sb->s_flags;
@@ -493,7 +494,7 @@ got_root:
        if (IS_ERR(root_inode))
                return PTR_ERR(root_inode);
 
-       if (AFFS_SB(sb)->s_flags & SF_INTL)
+       if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL))
                sb->s_d_op = &affs_intl_dentry_operations;
        else
                sb->s_d_op = &affs_dentry_operations;
@@ -520,10 +521,14 @@ affs_remount(struct super_block *sb, int *flags, char *data)
        int                      root_block;
        unsigned long            mount_flags;
        int                      res = 0;
-       char                    *new_opts = kstrdup(data, GFP_KERNEL);
+       char                    *new_opts;
        char                     volume[32];
        char                    *prefix = NULL;
 
+       new_opts = kstrdup(data, GFP_KERNEL);
+       if (!new_opts)
+               return -ENOMEM;
+
        pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data);
 
        sync_filesystem(sb);
index 3a7813a..1fead8d 100644 (file)
@@ -19,16 +19,16 @@ typedef u64 befs_blocknr_t;
  * BeFS in memory structures
  */
 
-typedef struct befs_mount_options {
+struct befs_mount_options {
        kgid_t gid;
        kuid_t uid;
        int use_gid;
        int use_uid;
        int debug;
        char *iocharset;
-} befs_mount_options;
+};
 
-typedef struct befs_sb_info {
+struct befs_sb_info {
        u32 magic1;
        u32 block_size;
        u32 block_shift;
@@ -52,12 +52,11 @@ typedef struct befs_sb_info {
        befs_inode_addr indices;
        u32 magic3;
 
-       befs_mount_options mount_opts;
+       struct befs_mount_options mount_opts;
        struct nls_table *nls;
+};
 
-} befs_sb_info;
-
-typedef struct befs_inode_info {
+struct befs_inode_info {
        u32 i_flags;
        u32 i_type;
 
@@ -71,8 +70,7 @@ typedef struct befs_inode_info {
        } i_data;
 
        struct inode vfs_inode;
-
-} befs_inode_info;
+};
 
 enum befs_err {
        BEFS_OK,
@@ -105,13 +103,13 @@ void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
 /* Gets a pointer to the private portion of the super_block
  * structure from the public part
  */
-static inline befs_sb_info *
+static inline struct befs_sb_info *
 BEFS_SB(const struct super_block *super)
 {
-       return (befs_sb_info *) super->s_fs_info;
+       return (struct befs_sb_info *) super->s_fs_info;
 }
 
-static inline befs_inode_info *
+static inline struct befs_inode_info *
 BEFS_I(const struct inode *inode)
 {
        return list_entry(inode, struct befs_inode_info, vfs_inode);
index 1e8e0b8..ebd5071 100644 (file)
@@ -168,7 +168,7 @@ befs_count_blocks(struct super_block * sb, befs_data_stream * ds)
        befs_blocknr_t blocks;
        befs_blocknr_t datablocks;      /* File data blocks */
        befs_blocknr_t metablocks;      /* FS metadata blocks */
-       befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
        befs_debug(sb, "---> %s", __func__);
 
@@ -428,7 +428,7 @@ befs_find_brun_dblindirect(struct super_block *sb,
        struct buffer_head *indir_block;
        befs_block_run indir_run;
        befs_disk_inode_addr *iaddr_array = NULL;
-       befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
        befs_blocknr_t indir_start_blk =
            data->max_indirect_range >> befs_sb->block_shift;
index 0408a3d..7a5b4ec 100644 (file)
@@ -28,7 +28,7 @@ befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
 {
        struct buffer_head *bh = NULL;
        befs_blocknr_t block = 0;
-       befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
        befs_debug(sb, "---> Enter %s "
                   "[%u, %hu, %hu]", __func__, iaddr.allocation_group,
index e089f19..16e0a48 100644 (file)
@@ -51,7 +51,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
 static void befs_put_super(struct super_block *);
 static int befs_remount(struct super_block *, int *, char *);
 static int befs_statfs(struct dentry *, struct kstatfs *);
-static int parse_options(char *, befs_mount_options *);
+static int parse_options(char *, struct befs_mount_options *);
 
 static const struct super_operations befs_sops = {
        .alloc_inode    = befs_alloc_inode,     /* allocate a new inode */
@@ -304,9 +304,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
 {
        struct buffer_head *bh = NULL;
        befs_inode *raw_inode = NULL;
-
-       befs_sb_info *befs_sb = BEFS_SB(sb);
-       befs_inode_info *befs_ino = NULL;
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_inode_info *befs_ino = NULL;
        struct inode *inode;
        long ret = -EIO;
 
@@ -472,7 +471,7 @@ static void *
 befs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct super_block *sb = dentry->d_sb;
-       befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+       struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
        befs_data_stream *data = &befs_ino->i_data.ds;
        befs_off_t len = data->size;
        char *link;
@@ -502,7 +501,8 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
 static void *
 befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+       struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+
        nd_set_link(nd, befs_ino->i_data.symlink);
        return NULL;
 }
@@ -669,7 +669,7 @@ static const match_table_t befs_tokens = {
 };
 
 static int
-parse_options(char *options, befs_mount_options * opts)
+parse_options(char *options, struct befs_mount_options *opts)
 {
        char *p;
        substring_t args[MAX_OPT_ARGS];
@@ -769,7 +769,7 @@ static int
 befs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct buffer_head *bh;
-       befs_sb_info *befs_sb;
+       struct befs_sb_info *befs_sb;
        befs_super_block *disk_sb;
        struct inode *root;
        long ret = -EINVAL;
index ca40f82..aeafc4d 100644 (file)
@@ -24,7 +24,7 @@
 int
 befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
 {
-       befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
        /* Check the byte order of the filesystem */
        if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
@@ -59,7 +59,7 @@ befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
 int
 befs_check_sb(struct super_block *sb)
 {
-       befs_sb_info *befs_sb = BEFS_SB(sb);
+       struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
        /* Check magic headers of super block */
        if ((befs_sb->magic1 != BEFS_SUPER_MAGIC1)
index 08063ae..7a81827 100644 (file)
@@ -86,7 +86,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        inode = new_inode(s);
        if (!inode)
-               return -ENOSPC;
+               return -ENOMEM;
        mutex_lock(&info->bfs_lock);
        ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1);
        if (ino > info->si_lasti) {
@@ -293,7 +293,7 @@ static int bfs_add_entry(struct inode *dir, const unsigned char *name,
        for (block = sblock; block <= eblock; block++) {
                bh = sb_bread(dir->i_sb, block);
                if (!bh)
-                       return -ENOSPC;
+                       return -EIO;
                for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
                        de = (struct bfs_dirent *)(bh->b_data + off);
                        if (!de->ino) {
index 97aff28..9dcb054 100644 (file)
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
@@ -521,9 +522,8 @@ static int parse_command(const char __user *buffer, size_t count)
 
 static void entry_status(Node *e, char *page)
 {
-       char *dp;
-       char *status = "disabled";
-       const char *flags = "flags: ";
+       char *dp = page;
+       const char *status = "disabled";
 
        if (test_bit(Enabled, &e->flags))
                status = "enabled";
@@ -533,12 +533,10 @@ static void entry_status(Node *e, char *page)
                return;
        }
 
-       sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter);
-       dp = page + strlen(page);
+       dp += sprintf(dp, "%s\ninterpreter %s\n", status, e->interpreter);
 
        /* print the special flags */
-       sprintf(dp, "%s", flags);
-       dp += strlen(flags);
+       dp += sprintf(dp, "flags: ");
        if (e->flags & MISC_FMT_PRESERVE_ARGV0)
                *dp++ = 'P';
        if (e->flags & MISC_FMT_OPEN_BINARY)
@@ -550,21 +548,11 @@ static void entry_status(Node *e, char *page)
        if (!test_bit(Magic, &e->flags)) {
                sprintf(dp, "extension .%s\n", e->magic);
        } else {
-               int i;
-
-               sprintf(dp, "offset %i\nmagic ", e->offset);
-               dp = page + strlen(page);
-               for (i = 0; i < e->size; i++) {
-                       sprintf(dp, "%02x", 0xff & (int) (e->magic[i]));
-                       dp += 2;
-               }
+               dp += sprintf(dp, "offset %i\nmagic ", e->offset);
+               dp = bin2hex(dp, e->magic, e->size);
                if (e->mask) {
-                       sprintf(dp, "\nmask ");
-                       dp += 6;
-                       for (i = 0; i < e->size; i++) {
-                               sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
-                               dp += 2;
-                       }
+                       dp += sprintf(dp, "\nmask ");
+                       dp = bin2hex(dp, e->mask, e->size);
                }
                *dp++ = '\n';
                *dp = '\0';
index c7f9b73..02bfd98 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -926,10 +926,14 @@ static int de_thread(struct task_struct *tsk)
        if (!thread_group_leader(tsk)) {
                struct task_struct *leader = tsk->group_leader;
 
-               sig->notify_count = -1; /* for exit_notify() */
                for (;;) {
                        threadgroup_change_begin(tsk);
                        write_lock_irq(&tasklist_lock);
+                       /*
+                        * Do this under tasklist_lock to ensure that
+                        * exit_notify() can't miss ->group_exit_task
+                        */
+                       sig->notify_count = -1;
                        if (likely(leader->exit_state))
                                break;
                        __set_current_state(TASK_KILLABLE);
@@ -1078,7 +1082,13 @@ int flush_old_exec(struct linux_binprm * bprm)
        if (retval)
                goto out;
 
+       /*
+        * Must be called _before_ exec_mmap() as bprm->mm is
+        * not visibile until then. This also enables the update
+        * to be lockless.
+        */
        set_mm_exe_file(bprm->mm, bprm->file);
+
        /*
         * Release all of the old mmap stuff
         */
index 91ad9e1..93fc622 100644 (file)
@@ -8,9 +8,7 @@
  *  May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
  */
 
-#include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
 #include "fat.h"
 
 /* this must be > 0. */
index c5d6bb9..4afc4d9 100644 (file)
  *  Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
  */
 
-#include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/buffer_head.h>
 #include <linux/compat.h>
 #include <linux/uaccess.h>
-#include <linux/kernel.h>
 #include "fat.h"
 
 /*
index 64e295e..be5e153 100644 (file)
@@ -2,11 +2,8 @@
 #define _FAT_H
 
 #include <linux/buffer_head.h>
-#include <linux/string.h>
 #include <linux/nls.h>
-#include <linux/fs.h>
 #include <linux/hash.h>
-#include <linux/mutex.h>
 #include <linux/ratelimit.h>
 #include <linux/msdos_fs.h>
 
@@ -66,7 +63,7 @@ struct msdos_sb_info {
        unsigned short sec_per_clus;  /* sectors/cluster */
        unsigned short cluster_bits;  /* log2(cluster_size) */
        unsigned int cluster_size;    /* cluster size */
-       unsigned char fats, fat_bits; /* number of FATs, FAT bits (12 or 16) */
+       unsigned char fats, fat_bits; /* number of FATs, FAT bits (12,16 or 32) */
        unsigned short fat_start;
        unsigned long fat_length;     /* FAT start & length (sec.) */
        unsigned long dir_start;
index 260705c..8226557 100644 (file)
@@ -3,9 +3,6 @@
  * Released under GPL v2.
  */
 
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
 #include <linux/blkdev.h>
 #include "fat.h"
 
index 1e98d33..cf50d93 100644 (file)
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
-#include <linux/time.h>
-#include <linux/buffer_head.h>
-#include <linux/writeback.h>
-#include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
index 41b7299..c067746 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
-#include <linux/buffer_head.h>
-#include <linux/mount.h>
 #include <linux/vfs.h>
+#include <linux/seq_file.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
-#include <linux/writeback.h>
-#include <linux/log2.h>
-#include <linux/hash.h>
 #include <linux/blkdev.h>
 #include <asm/unaligned.h>
 #include "fat.h"
@@ -1278,8 +1270,7 @@ out:
 
 static int fat_read_root(struct inode *inode)
 {
-       struct super_block *sb = inode->i_sb;
-       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
        int error;
 
        MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO;
index d8da2d2..c4589e9 100644 (file)
@@ -6,10 +6,6 @@
  *              and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
  */
 
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/buffer_head.h>
-#include <linux/time.h>
 #include "fat.h"
 
 /*
index a783b0e..cc6a854 100644 (file)
@@ -7,8 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/time.h>
-#include <linux/buffer_head.h>
 #include "fat.h"
 
 /* Characters that are undesirable in an MS-DOS file name */
index b8b92c2..7e0974e 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/jiffies.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
 #include <linux/namei.h>
 #include "fat.h"
 
index ee738ea..93c5f89 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -638,8 +638,7 @@ static struct file *__fget(unsigned int fd, fmode_t mask)
        file = fcheck_files(files, fd);
        if (file) {
                /* File object ref couldn't be taken */
-               if ((file->f_mode & mask) ||
-                   !atomic_long_inc_not_zero(&file->f_count))
+               if ((file->f_mode & mask) || !get_file_rcu(file))
                        file = NULL;
        }
        rcu_read_unlock();
index 1455668..36d1a6a 100644 (file)
@@ -197,7 +197,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        inode = hfs_new_inode(dir, &dentry->d_name, mode);
        if (!inode)
-               return -ENOSPC;
+               return -ENOMEM;
 
        res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
        if (res) {
@@ -226,7 +226,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode);
        if (!inode)
-               return -ENOSPC;
+               return -ENOMEM;
 
        res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
        if (res) {
index c1422d9..528e38b 100644 (file)
@@ -118,9 +118,7 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd,
        int b, e;
        int res;
 
-       if (!rec_found)
-               BUG();
-
+       BUG_ON(!rec_found);
        b = 0;
        e = bnode->num_recs - 1;
        res = -ENOENT;
index 7892e6f..022974a 100644 (file)
@@ -350,10 +350,11 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
                        &fd.search_key->cat.name.unicode,
                        off + 2, len);
                fd.search_key->key_len = cpu_to_be16(6 + len);
-       } else
+       } else {
                err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
                if (unlikely(err))
                        goto out;
+       }
 
        err = hfs_brec_find(&fd, hfs_find_rec_by_key);
        if (err)
index f0235c1..3074609 100644 (file)
@@ -434,7 +434,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
        struct inode *inode;
-       int res = -ENOSPC;
+       int res = -ENOMEM;
 
        mutex_lock(&sbi->vh_mutex);
        inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO);
@@ -476,7 +476,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
        struct inode *inode;
-       int res = -ENOSPC;
+       int res = -ENOMEM;
 
        mutex_lock(&sbi->vh_mutex);
        inode = hfsplus_new_inode(dir->i_sb, mode);
index a43811f..b0afedb 100644 (file)
@@ -253,6 +253,12 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
                inode_dio_wait(inode);
+               if (attr->ia_size > inode->i_size) {
+                       error = generic_cont_expand_simple(inode,
+                                                          attr->ia_size);
+                       if (error)
+                               return error;
+               }
                truncate_setsize(inode, attr->ia_size);
                hfsplus_file_truncate(inode);
        }
index d3ff5cc..8e98f5d 100644 (file)
@@ -76,7 +76,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
 {
        struct inode *inode = file_inode(file);
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
-       unsigned int flags;
+       unsigned int flags, new_fl = 0;
        int err = 0;
 
        err = mnt_want_write_file(file);
@@ -110,14 +110,12 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
        }
 
        if (flags & FS_IMMUTABLE_FL)
-               inode->i_flags |= S_IMMUTABLE;
-       else
-               inode->i_flags &= ~S_IMMUTABLE;
+               new_fl |= S_IMMUTABLE;
 
        if (flags & FS_APPEND_FL)
-               inode->i_flags |= S_APPEND;
-       else
-               inode->i_flags &= ~S_APPEND;
+               new_fl |= S_APPEND;
+
+       inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND);
 
        if (flags & FS_NODUMP_FL)
                hip->userflags |= HFSPLUS_FLG_NODUMP;
index d98094a..89f262d 100644 (file)
@@ -44,7 +44,7 @@ static int strcmp_xattr_acl(const char *name)
        return -1;
 }
 
-static inline int is_known_namespace(const char *name)
+static bool is_known_namespace(const char *name)
 {
        if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) &&
            strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
@@ -424,6 +424,28 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
        return len;
 }
 
+int hfsplus_setxattr(struct dentry *dentry, const char *name,
+                    const void *value, size_t size, int flags,
+                    const char *prefix, size_t prefixlen)
+{
+       char *xattr_name;
+       int res;
+
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
+               GFP_KERNEL);
+       if (!xattr_name)
+               return -ENOMEM;
+       strcpy(xattr_name, prefix);
+       strcpy(xattr_name + prefixlen, name);
+       res = __hfsplus_setxattr(dentry->d_inode, xattr_name, value, size,
+                                flags);
+       kfree(xattr_name);
+       return res;
+}
+
 static ssize_t hfsplus_getxattr_finder_info(struct inode *inode,
                                                void *value, size_t size)
 {
@@ -560,6 +582,30 @@ failed_getxattr_init:
        return res;
 }
 
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+                        void *value, size_t size,
+                        const char *prefix, size_t prefixlen)
+{
+       int res;
+       char *xattr_name;
+
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
+                            GFP_KERNEL);
+       if (!xattr_name)
+               return -ENOMEM;
+
+       strcpy(xattr_name, prefix);
+       strcpy(xattr_name + prefixlen, name);
+
+       res = __hfsplus_getxattr(dentry->d_inode, xattr_name, value, size);
+       kfree(xattr_name);
+       return res;
+
+}
+
 static inline int can_list(const char *xattr_name)
 {
        if (!xattr_name)
@@ -806,9 +852,6 @@ end_removexattr:
 static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
                                        void *buffer, size_t size, int type)
 {
-       char *xattr_name;
-       int res;
-
        if (!strcmp(name, ""))
                return -EINVAL;
 
@@ -818,24 +861,19 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
         */
        if (is_known_namespace(name))
                return -EOPNOTSUPP;
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN
-               + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
-       strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
 
-       res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
-       kfree(xattr_name);
-       return res;
+       /*
+        * osx is the namespace we use to indicate an unprefixed
+        * attribute on the filesystem (like the ones that OS X
+        * creates), so we pass the name through unmodified (after
+        * ensuring it doesn't conflict with another namespace).
+        */
+       return __hfsplus_getxattr(dentry->d_inode, name, buffer, size);
 }
 
 static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
                const void *buffer, size_t size, int flags, int type)
 {
-       char *xattr_name;
-       int res;
-
        if (!strcmp(name, ""))
                return -EINVAL;
 
@@ -845,16 +883,14 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
         */
        if (is_known_namespace(name))
                return -EOPNOTSUPP;
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN
-               + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
-       strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
 
-       res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
-       kfree(xattr_name);
-       return res;
+       /*
+        * osx is the namespace we use to indicate an unprefixed
+        * attribute on the filesystem (like the ones that OS X
+        * creates), so we pass the name through unmodified (after
+        * ensuring it doesn't conflict with another namespace).
+        */
+       return __hfsplus_setxattr(dentry->d_inode, name, buffer, size, flags);
 }
 
 static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
index 288530c..f9b0955 100644 (file)
@@ -21,22 +21,16 @@ extern const struct xattr_handler *hfsplus_xattr_handlers[];
 int __hfsplus_setxattr(struct inode *inode, const char *name,
                        const void *value, size_t size, int flags);
 
-static inline int hfsplus_setxattr(struct dentry *dentry, const char *name,
-                       const void *value, size_t size, int flags)
-{
-       return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags);
-}
+int hfsplus_setxattr(struct dentry *dentry, const char *name,
+                                  const void *value, size_t size, int flags,
+                                  const char *prefix, size_t prefixlen);
 
 ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
-                       void *value, size_t size);
-
-static inline ssize_t hfsplus_getxattr(struct dentry *dentry,
-                                       const char *name,
-                                       void *value,
-                                       size_t size)
-{
-       return __hfsplus_getxattr(dentry->d_inode, name, value, size);
-}
+                          void *value, size_t size);
+
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+                        void *value, size_t size,
+                        const char *prefix, size_t prefixlen);
 
 ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
index 6ec5e10..aacff00 100644 (file)
 static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
                                        void *buffer, size_t size, int type)
 {
-       char *xattr_name;
-       int res;
-
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_SECURITY_PREFIX);
-       strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
-
-       res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_getxattr(dentry, name, buffer, size,
+                               XATTR_SECURITY_PREFIX,
+                               XATTR_SECURITY_PREFIX_LEN);
 }
 
 static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
                const void *buffer, size_t size, int flags, int type)
 {
-       char *xattr_name;
-       int res;
-
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_SECURITY_PREFIX);
-       strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
-
-       res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_setxattr(dentry, name, buffer, size, flags,
+                               XATTR_SECURITY_PREFIX,
+                               XATTR_SECURITY_PREFIX_LEN);
 }
 
 static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
index 3c5f27e..bcf6508 100644 (file)
 static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
                                        void *buffer, size_t size, int type)
 {
-       char *xattr_name;
-       int res;
-
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
-       strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
-
-       res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_getxattr(dentry, name, buffer, size,
+                               XATTR_TRUSTED_PREFIX,
+                               XATTR_TRUSTED_PREFIX_LEN);
 }
 
 static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
                const void *buffer, size_t size, int flags, int type)
 {
-       char *xattr_name;
-       int res;
-
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
-       strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
-
-       res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_setxattr(dentry, name, buffer, size, flags,
+                               XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
 static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
index 2b625a5..5aa0e6d 100644 (file)
 static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
                                        void *buffer, size_t size, int type)
 {
-       char *xattr_name;
-       int res;
 
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_USER_PREFIX);
-       strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
-
-       res = hfsplus_getxattr(dentry, xattr_name, buffer, size);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_getxattr(dentry, name, buffer, size,
+                               XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
 static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
                const void *buffer, size_t size, int flags, int type)
 {
-       char *xattr_name;
-       int res;
-
-       if (!strcmp(name, ""))
-               return -EINVAL;
-
-       xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
-               GFP_KERNEL);
-       if (!xattr_name)
-               return -ENOMEM;
-       strcpy(xattr_name, XATTR_USER_PREFIX);
-       strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
-
-       res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
-       kfree(xattr_name);
-       return res;
+       return hfsplus_setxattr(dentry, name, buffer, size, flags,
+                               XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
 static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
index 52b780f..653faab 100644 (file)
@@ -2590,6 +2590,44 @@ static int locks_show(struct seq_file *f, void *v)
        return 0;
 }
 
+static void __show_fd_locks(struct seq_file *f,
+                       struct list_head *head, int *id,
+                       struct file *filp, struct files_struct *files)
+{
+       struct file_lock *fl;
+
+       list_for_each_entry(fl, head, fl_list) {
+
+               if (filp != fl->fl_file)
+                       continue;
+               if (fl->fl_owner != files &&
+                   fl->fl_owner != filp)
+                       continue;
+
+               (*id)++;
+               seq_puts(f, "lock:\t");
+               lock_get_status(f, fl, *id, "");
+       }
+}
+
+void show_fd_locks(struct seq_file *f,
+                 struct file *filp, struct files_struct *files)
+{
+       struct inode *inode = file_inode(filp);
+       struct file_lock_context *ctx;
+       int id = 0;
+
+       ctx = inode->i_flctx;
+       if (!ctx)
+               return;
+
+       spin_lock(&ctx->flc_lock);
+       __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
+       __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
+       __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
+       spin_unlock(&ctx->flc_lock);
+}
+
 static void *locks_start(struct seq_file *f, loff_t *pos)
        __acquires(&blocked_lock_lock)
 {
index 741fd02..8df0f3b 100644 (file)
@@ -405,13 +405,14 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode,
 static int nilfs_palloc_count_desc_blocks(struct inode *inode,
                                            unsigned long *desc_blocks)
 {
-       unsigned long blknum;
+       __u64 blknum;
        int ret;
 
        ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum);
        if (likely(!ret))
                *desc_blocks = DIV_ROUND_UP(
-                       blknum, NILFS_MDT(inode)->mi_blocks_per_desc_block);
+                       (unsigned long)blknum,
+                       NILFS_MDT(inode)->mi_blocks_per_desc_block);
        return ret;
 }
 
index aadbd0b..27f75bc 100644 (file)
@@ -152,9 +152,7 @@ static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
  *
  * %-EEXIST - A record associated with @key already exist.
  */
-int nilfs_bmap_insert(struct nilfs_bmap *bmap,
-                     unsigned long key,
-                     unsigned long rec)
+int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec)
 {
        int ret;
 
@@ -191,19 +189,47 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
        return bmap->b_ops->bop_delete(bmap, key);
 }
 
-int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
+/**
+ * nilfs_bmap_seek_key - seek a valid entry and return its key
+ * @bmap: bmap struct
+ * @start: start key number
+ * @keyp: place to store valid key
+ *
+ * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap
+ * starting from @start, and stores it to @keyp if found.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the following
+ * negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-ENOENT - No valid entry was found
+ */
+int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp)
 {
-       __u64 lastkey;
        int ret;
 
        down_read(&bmap->b_sem);
-       ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
+       ret = bmap->b_ops->bop_seek_key(bmap, start, keyp);
+       up_read(&bmap->b_sem);
+
+       if (ret < 0)
+               ret = nilfs_bmap_convert_error(bmap, __func__, ret);
+       return ret;
+}
+
+int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp)
+{
+       int ret;
+
+       down_read(&bmap->b_sem);
+       ret = bmap->b_ops->bop_last_key(bmap, keyp);
        up_read(&bmap->b_sem);
 
        if (ret < 0)
                ret = nilfs_bmap_convert_error(bmap, __func__, ret);
-       else
-               *key = lastkey;
        return ret;
 }
 
@@ -224,7 +250,7 @@ int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
  *
  * %-ENOENT - A record associated with @key does not exist.
  */
-int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
+int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key)
 {
        int ret;
 
@@ -235,7 +261,7 @@ int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
        return nilfs_bmap_convert_error(bmap, __func__, ret);
 }
 
-static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
+static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key)
 {
        __u64 lastkey;
        int ret;
@@ -276,7 +302,7 @@ static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
  *
  * %-ENOMEM - Insufficient amount of memory available.
  */
-int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key)
+int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key)
 {
        int ret;
 
index b89e680..bfa817c 100644 (file)
@@ -76,8 +76,10 @@ struct nilfs_bmap_operations {
                          union nilfs_binfo *);
        int (*bop_mark)(struct nilfs_bmap *, __u64, int);
 
-       /* The following functions are internal use only. */
+       int (*bop_seek_key)(const struct nilfs_bmap *, __u64, __u64 *);
        int (*bop_last_key)(const struct nilfs_bmap *, __u64 *);
+
+       /* The following functions are internal use only. */
        int (*bop_check_insert)(const struct nilfs_bmap *, __u64);
        int (*bop_check_delete)(struct nilfs_bmap *, __u64);
        int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int);
@@ -153,10 +155,11 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
 int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
 void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
 int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
-int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
-int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
-int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
-int nilfs_bmap_truncate(struct nilfs_bmap *, unsigned long);
+int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec);
+int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key);
+int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp);
+int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp);
+int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key);
 void nilfs_bmap_clear(struct nilfs_bmap *);
 int nilfs_bmap_propagate(struct nilfs_bmap *, struct buffer_head *);
 void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *, struct list_head *);
index ecdbae1..059f371 100644 (file)
@@ -633,6 +633,44 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree,
        return 0;
 }
 
+/**
+ * nilfs_btree_get_next_key - get next valid key from btree path array
+ * @btree: bmap struct of btree
+ * @path: array of nilfs_btree_path struct
+ * @minlevel: start level
+ * @nextkey: place to store the next valid key
+ *
+ * Return Value: If a next key was found, 0 is returned. Otherwise,
+ * -ENOENT is returned.
+ */
+static int nilfs_btree_get_next_key(const struct nilfs_bmap *btree,
+                                   const struct nilfs_btree_path *path,
+                                   int minlevel, __u64 *nextkey)
+{
+       struct nilfs_btree_node *node;
+       int maxlevel = nilfs_btree_height(btree) - 1;
+       int index, next_adj, level;
+
+       /* Next index is already set to bp_index for leaf nodes. */
+       next_adj = 0;
+       for (level = minlevel; level <= maxlevel; level++) {
+               if (level == maxlevel)
+                       node = nilfs_btree_get_root(btree);
+               else
+                       node = nilfs_btree_get_nonroot_node(path, level);
+
+               index = path[level].bp_index + next_adj;
+               if (index < nilfs_btree_node_get_nchildren(node)) {
+                       /* Next key is in this node */
+                       *nextkey = nilfs_btree_node_get_key(node, index);
+                       return 0;
+               }
+               /* For non-leaf nodes, next index is stored at bp_index + 1. */
+               next_adj = 1;
+       }
+       return -ENOENT;
+}
+
 static int nilfs_btree_lookup(const struct nilfs_bmap *btree,
                              __u64 key, int level, __u64 *ptrp)
 {
@@ -1563,6 +1601,27 @@ out:
        return ret;
 }
 
+static int nilfs_btree_seek_key(const struct nilfs_bmap *btree, __u64 start,
+                               __u64 *keyp)
+{
+       struct nilfs_btree_path *path;
+       const int minlevel = NILFS_BTREE_LEVEL_NODE_MIN;
+       int ret;
+
+       path = nilfs_btree_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       ret = nilfs_btree_do_lookup(btree, path, start, NULL, minlevel, 0);
+       if (!ret)
+               *keyp = start;
+       else if (ret == -ENOENT)
+               ret = nilfs_btree_get_next_key(btree, path, minlevel, keyp);
+
+       nilfs_btree_free_path(path);
+       return ret;
+}
+
 static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp)
 {
        struct nilfs_btree_path *path;
@@ -2298,7 +2357,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = {
        .bop_assign             =       nilfs_btree_assign,
        .bop_mark               =       nilfs_btree_mark,
 
+       .bop_seek_key           =       nilfs_btree_seek_key,
        .bop_last_key           =       nilfs_btree_last_key,
+
        .bop_check_insert       =       NULL,
        .bop_check_delete       =       nilfs_btree_check_delete,
        .bop_gather_data        =       nilfs_btree_gather_data,
@@ -2318,7 +2379,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
        .bop_assign             =       nilfs_btree_assign_gc,
        .bop_mark               =       NULL,
 
+       .bop_seek_key           =       NULL,
        .bop_last_key           =       NULL,
+
        .bop_check_insert       =       NULL,
        .bop_check_delete       =       NULL,
        .bop_gather_data        =       NULL,
index 0d58075..b6596ca 100644 (file)
@@ -53,6 +53,13 @@ nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno)
        return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile));
 }
 
+static __u64 nilfs_cpfile_first_checkpoint_in_block(const struct inode *cpfile,
+                                                   unsigned long blkoff)
+{
+       return (__u64)nilfs_cpfile_checkpoints_per_block(cpfile) * blkoff
+               + 1 - NILFS_MDT(cpfile)->mi_first_entry_offset;
+}
+
 static unsigned long
 nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile,
                                  __u64 curr,
@@ -146,6 +153,44 @@ static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile,
                                   create, nilfs_cpfile_block_init, bhp);
 }
 
+/**
+ * nilfs_cpfile_find_checkpoint_block - find and get a buffer on cpfile
+ * @cpfile: inode of cpfile
+ * @start_cno: start checkpoint number (inclusive)
+ * @end_cno: end checkpoint number (inclusive)
+ * @cnop: place to store the next checkpoint number
+ * @bhp: place to store a pointer to buffer_head struct
+ *
+ * Return Value: On success, it returns 0. On error, the following negative
+ * error code is returned.
+ *
+ * %-ENOMEM - Insufficient memory available.
+ *
+ * %-EIO - I/O error
+ *
+ * %-ENOENT - no block exists in the range.
+ */
+static int nilfs_cpfile_find_checkpoint_block(struct inode *cpfile,
+                                             __u64 start_cno, __u64 end_cno,
+                                             __u64 *cnop,
+                                             struct buffer_head **bhp)
+{
+       unsigned long start, end, blkoff;
+       int ret;
+
+       if (unlikely(start_cno > end_cno))
+               return -ENOENT;
+
+       start = nilfs_cpfile_get_blkoff(cpfile, start_cno);
+       end = nilfs_cpfile_get_blkoff(cpfile, end_cno);
+
+       ret = nilfs_mdt_find_block(cpfile, start, end, &blkoff, bhp);
+       if (!ret)
+               *cnop = (blkoff == start) ? start_cno :
+                       nilfs_cpfile_first_checkpoint_in_block(cpfile, blkoff);
+       return ret;
+}
+
 static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile,
                                                       __u64 cno)
 {
@@ -403,14 +448,15 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
                return -ENOENT; /* checkpoint number 0 is invalid */
        down_read(&NILFS_MDT(cpfile)->mi_sem);
 
-       for (n = 0; cno < cur_cno && n < nci; cno += ncps) {
-               ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno);
-               ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
+       for (n = 0; n < nci; cno += ncps) {
+               ret = nilfs_cpfile_find_checkpoint_block(
+                       cpfile, cno, cur_cno - 1, &cno, &bh);
                if (ret < 0) {
-                       if (ret != -ENOENT)
-                               goto out;
-                       continue; /* skip hole */
+                       if (likely(ret == -ENOENT))
+                               break;
+                       goto out;
                }
+               ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno);
 
                kaddr = kmap_atomic(bh->b_page);
                cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
index 82f4865..ebf89fd 100644 (file)
@@ -173,6 +173,21 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
        return ret;
 }
 
+static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start,
+                                __u64 *keyp)
+{
+       __u64 key;
+
+       for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) {
+               if (nilfs_direct_get_ptr(direct, key) !=
+                   NILFS_BMAP_INVALID_PTR) {
+                       *keyp = key;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+
 static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp)
 {
        __u64 key, lastkey;
@@ -355,7 +370,9 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = {
        .bop_assign             =       nilfs_direct_assign,
        .bop_mark               =       NULL,
 
+       .bop_seek_key           =       nilfs_direct_seek_key,
        .bop_last_key           =       nilfs_direct_last_key,
+
        .bop_check_insert       =       nilfs_direct_check_insert,
        .bop_check_delete       =       NULL,
        .bop_gather_data        =       nilfs_direct_gather_data,
index 36f057f..be936df 100644 (file)
@@ -106,7 +106,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
                err = nilfs_transaction_begin(inode->i_sb, &ti, 1);
                if (unlikely(err))
                        goto out;
-               err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff,
+               err = nilfs_bmap_insert(ii->i_bmap, blkoff,
                                        (unsigned long)bh_result);
                if (unlikely(err != 0)) {
                        if (err == -EEXIST) {
@@ -441,21 +441,20 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode)
 void nilfs_set_inode_flags(struct inode *inode)
 {
        unsigned int flags = NILFS_I(inode)->i_flags;
+       unsigned int new_fl = 0;
 
-       inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
-                           S_DIRSYNC);
        if (flags & FS_SYNC_FL)
-               inode->i_flags |= S_SYNC;
+               new_fl |= S_SYNC;
        if (flags & FS_APPEND_FL)
-               inode->i_flags |= S_APPEND;
+               new_fl |= S_APPEND;
        if (flags & FS_IMMUTABLE_FL)
-               inode->i_flags |= S_IMMUTABLE;
+               new_fl |= S_IMMUTABLE;
        if (flags & FS_NOATIME_FL)
-               inode->i_flags |= S_NOATIME;
+               new_fl |= S_NOATIME;
        if (flags & FS_DIRSYNC_FL)
-               inode->i_flags |= S_DIRSYNC;
-       mapping_set_gfp_mask(inode->i_mapping,
-                            mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+               new_fl |= S_DIRSYNC;
+       inode_set_flags(inode, new_fl, S_SYNC | S_APPEND | S_IMMUTABLE |
+                       S_NOATIME | S_DIRSYNC);
 }
 
 int nilfs_read_inode_common(struct inode *inode,
@@ -540,6 +539,8 @@ static int __nilfs_read_inode(struct super_block *sb,
        brelse(bh);
        up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
        nilfs_set_inode_flags(inode);
+       mapping_set_gfp_mask(inode->i_mapping,
+                            mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
        return 0;
 
  failed_unmap:
@@ -712,7 +713,7 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags)
 static void nilfs_truncate_bmap(struct nilfs_inode_info *ii,
                                unsigned long from)
 {
-       unsigned long b;
+       __u64 b;
        int ret;
 
        if (!test_bit(NILFS_I_BMAP, &ii->i_state))
@@ -727,7 +728,7 @@ repeat:
        if (b < from)
                return;
 
-       b -= min_t(unsigned long, NILFS_MAX_TRUNCATE_BLOCKS, b - from);
+       b -= min_t(__u64, NILFS_MAX_TRUNCATE_BLOCKS, b - from);
        ret = nilfs_bmap_truncate(ii->i_bmap, b);
        nilfs_relax_pressure_in_lock(ii->vfs_inode.i_sb);
        if (!ret || (ret == -ENOMEM &&
index 892cf5f..dee34d9 100644 (file)
@@ -260,6 +260,60 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,
        return ret;
 }
 
+/**
+ * nilfs_mdt_find_block - find and get a buffer on meta data file.
+ * @inode: inode of the meta data file
+ * @start: start block offset (inclusive)
+ * @end: end block offset (inclusive)
+ * @blkoff: block offset
+ * @out_bh: place to store a pointer to buffer_head struct
+ *
+ * nilfs_mdt_find_block() looks up an existing block in range of
+ * [@start, @end] and stores pointer to a buffer head of the block to
+ * @out_bh, and block offset to @blkoff, respectively.  @out_bh and
+ * @blkoff are substituted only when zero is returned.
+ *
+ * Return Value: On success, it returns 0. On error, the following negative
+ * error code is returned.
+ *
+ * %-ENOMEM - Insufficient memory available.
+ *
+ * %-EIO - I/O error
+ *
+ * %-ENOENT - no block was found in the range
+ */
+int nilfs_mdt_find_block(struct inode *inode, unsigned long start,
+                        unsigned long end, unsigned long *blkoff,
+                        struct buffer_head **out_bh)
+{
+       __u64 next;
+       int ret;
+
+       if (unlikely(start > end))
+               return -ENOENT;
+
+       ret = nilfs_mdt_read_block(inode, start, true, out_bh);
+       if (!ret) {
+               *blkoff = start;
+               goto out;
+       }
+       if (unlikely(ret != -ENOENT || start == ULONG_MAX))
+               goto out;
+
+       ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next);
+       if (!ret) {
+               if (next <= end) {
+                       ret = nilfs_mdt_read_block(inode, next, true, out_bh);
+                       if (!ret)
+                               *blkoff = next;
+               } else {
+                       ret = -ENOENT;
+               }
+       }
+out:
+       return ret;
+}
+
 /**
  * nilfs_mdt_delete_block - make a hole on the meta data file.
  * @inode: inode of the meta data file
index ab172e8..fe529a8 100644 (file)
@@ -78,6 +78,9 @@ int nilfs_mdt_get_block(struct inode *, unsigned long, int,
                        void (*init_block)(struct inode *,
                                           struct buffer_head *, void *),
                        struct buffer_head **);
+int nilfs_mdt_find_block(struct inode *inode, unsigned long start,
+                        unsigned long end, unsigned long *blkoff,
+                        struct buffer_head **out_bh);
 int nilfs_mdt_delete_block(struct inode *, unsigned long);
 int nilfs_mdt_forget_block(struct inode *, unsigned long);
 int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);
@@ -111,7 +114,10 @@ static inline __u64 nilfs_mdt_cno(struct inode *inode)
        return ((struct the_nilfs *)inode->i_sb->s_fs_info)->ns_cno;
 }
 
-#define nilfs_mdt_bgl_lock(inode, bg) \
-       (&NILFS_MDT(inode)->mi_bgl->locks[(bg) & (NR_BG_LOCKS-1)].lock)
+static inline spinlock_t *
+nilfs_mdt_bgl_lock(struct inode *inode, unsigned int block_group)
+{
+       return bgl_lock_ptr(NILFS_MDT(inode)->mi_bgl, block_group);
+}
 
 #endif /* _NILFS_MDT_H */
index 700ecbc..45d650a 100644 (file)
@@ -89,18 +89,16 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
 void nilfs_forget_buffer(struct buffer_head *bh)
 {
        struct page *page = bh->b_page;
+       const unsigned long clear_bits =
+               (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped |
+                1 << BH_Async_Write | 1 << BH_NILFS_Volatile |
+                1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected);
 
        lock_buffer(bh);
-       clear_buffer_nilfs_volatile(bh);
-       clear_buffer_nilfs_checked(bh);
-       clear_buffer_nilfs_redirected(bh);
-       clear_buffer_async_write(bh);
-       clear_buffer_dirty(bh);
+       set_mask_bits(&bh->b_state, clear_bits, 0);
        if (nilfs_page_buffers_clean(page))
                __nilfs_clear_page_dirty(page);
 
-       clear_buffer_uptodate(bh);
-       clear_buffer_mapped(bh);
        bh->b_blocknr = -1;
        ClearPageUptodate(page);
        ClearPageMappedToDisk(page);
@@ -421,6 +419,10 @@ void nilfs_clear_dirty_page(struct page *page, bool silent)
 
        if (page_has_buffers(page)) {
                struct buffer_head *bh, *head;
+               const unsigned long clear_bits =
+                       (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped |
+                        1 << BH_Async_Write | 1 << BH_NILFS_Volatile |
+                        1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected);
 
                bh = head = page_buffers(page);
                do {
@@ -430,13 +432,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent)
                                        "discard block %llu, size %zu",
                                        (u64)bh->b_blocknr, bh->b_size);
                        }
-                       clear_buffer_async_write(bh);
-                       clear_buffer_dirty(bh);
-                       clear_buffer_nilfs_volatile(bh);
-                       clear_buffer_nilfs_checked(bh);
-                       clear_buffer_nilfs_redirected(bh);
-                       clear_buffer_uptodate(bh);
-                       clear_buffer_mapped(bh);
+                       set_mask_bits(&bh->b_state, clear_bits, 0);
                        unlock_buffer(bh);
                } while (bh = bh->b_this_page, bh != head);
        }
index 0c3f303..c6abbad 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/bitops.h>
 #include <linux/bio.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
@@ -1588,7 +1589,6 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
 
                list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
                                    b_assoc_buffers) {
-                       set_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page) {
                                        lock_page(bd_page);
@@ -1688,7 +1688,6 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
        list_for_each_entry(segbuf, logs, sb_list) {
                list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
                                    b_assoc_buffers) {
-                       clear_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page)
                                        end_page_writeback(bd_page);
@@ -1768,7 +1767,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                                    b_assoc_buffers) {
                        set_buffer_uptodate(bh);
                        clear_buffer_dirty(bh);
-                       clear_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page)
                                        end_page_writeback(bd_page);
@@ -1788,12 +1786,13 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                 */
                list_for_each_entry(bh, &segbuf->sb_payload_buffers,
                                    b_assoc_buffers) {
-                       set_buffer_uptodate(bh);
-                       clear_buffer_dirty(bh);
-                       clear_buffer_async_write(bh);
-                       clear_buffer_delay(bh);
-                       clear_buffer_nilfs_volatile(bh);
-                       clear_buffer_nilfs_redirected(bh);
+                       const unsigned long set_bits = (1 << BH_Uptodate);
+                       const unsigned long clear_bits =
+                               (1 << BH_Dirty | 1 << BH_Async_Write |
+                                1 << BH_Delay | 1 << BH_NILFS_Volatile |
+                                1 << BH_NILFS_Redirected);
+
+                       set_mask_bits(&bh->b_state, clear_bits, set_bits);
                        if (bh == segbuf->sb_super_root) {
                                if (bh->b_page != bd_page) {
                                        end_page_writeback(bd_page);
index 5bc2a1c..c1725f2 100644 (file)
@@ -1020,7 +1020,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
        struct dentry *dentry;
        int ret;
 
-       if (cno < 0 || cno > nilfs->ns_cno)
+       if (cno > nilfs->ns_cno)
                return false;
 
        if (cno >= nilfs_last_cno(nilfs))
index 8e5ad83..af84ad0 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/security.h>
 #include <linux/file.h>
 #include <linux/seq_file.h>
+#include <linux/fs.h>
 
 #include <linux/proc_fs.h>
 
@@ -48,17 +49,23 @@ static int seq_show(struct seq_file *m, void *v)
                put_files_struct(files);
        }
 
-       if (!ret) {
-               seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
-                          (long long)file->f_pos, f_flags,
-                          real_mount(file->f_path.mnt)->mnt_id);
-               if (file->f_op->show_fdinfo)
-                       file->f_op->show_fdinfo(m, file);
-               ret = seq_has_overflowed(m);
-               fput(file);
-       }
+       if (ret)
+               return ret;
 
-       return ret;
+       seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
+                  (long long)file->f_pos, f_flags,
+                  real_mount(file->f_path.mnt)->mnt_id);
+
+       show_fd_locks(m, file, files);
+       if (seq_has_overflowed(m))
+               goto out;
+
+       if (file->f_op->show_fdinfo)
+               file->f_op->show_fdinfo(m, file);
+
+out:
+       fput(file);
+       return 0;
 }
 
 static int seq_fdinfo_open(struct inode *inode, struct file *file)
index 9fa1f65..c9ccafa 100644 (file)
@@ -17,7 +17,9 @@
 #define __NR_seccomp_read_32           __NR_read
 #define __NR_seccomp_write_32          __NR_write
 #define __NR_seccomp_exit_32           __NR_exit
+#ifndef __NR_seccomp_sigreturn_32
 #define __NR_seccomp_sigreturn_32      __NR_rt_sigreturn
+#endif
 #endif /* CONFIG_COMPAT && ! already defined */
 
 #define __NR_seccomp_read              __NR_read
index be4fa5d..ea17cca 100644 (file)
@@ -283,16 +283,16 @@ static inline int bitmap_empty(const unsigned long *src, unsigned nbits)
 {
        if (small_const_nbits(nbits))
                return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
-       else
-               return __bitmap_empty(src, nbits);
+
+       return find_first_bit(src, nbits) == nbits;
 }
 
 static inline int bitmap_full(const unsigned long *src, unsigned int nbits)
 {
        if (small_const_nbits(nbits))
                return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
-       else
-               return __bitmap_full(src, nbits);
+
+       return find_first_zero_bit(src, nbits) == nbits;
 }
 
 static inline int bitmap_weight(const unsigned long *src, unsigned int nbits)
index 5d858e0..297f5bd 100644 (file)
@@ -218,9 +218,9 @@ static inline unsigned long __ffs64(u64 word)
 /**
  * find_last_bit - find the last set bit in a memory region
  * @addr: The address to start the search at
- * @size: The maximum size to search
+ * @size: The number of bits to search
  *
- * Returns the bit number of the first set bit, or size.
+ * Returns the bit number of the last set bit, or size.
  */
 extern unsigned long find_last_bit(const unsigned long *addr,
                                   unsigned long size);
index f4d6354..c7496f2 100644 (file)
@@ -875,6 +875,7 @@ static inline struct file *get_file(struct file *f)
        atomic_long_inc(&f->f_count);
        return f;
 }
+#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count)
 #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
 #define file_count(x)  atomic_long_read(&(x)->f_count)
 
@@ -1046,6 +1047,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
 extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
 extern int lease_modify(struct file_lock *, int, struct list_head *);
+struct files_struct;
+extern void show_fd_locks(struct seq_file *f,
+                        struct file *filp, struct files_struct *files);
 #else /* !CONFIG_FILE_LOCKING */
 static inline int fcntl_getlk(struct file *file, unsigned int cmd,
                              struct flock __user *user)
@@ -1182,6 +1186,10 @@ static inline int lease_modify(struct file_lock *fl, int arg,
 {
        return -EINVAL;
 }
+
+struct files_struct;
+static inline void show_fd_locks(struct seq_file *f,
+                       struct file *filp, struct files_struct *files) {}
 #endif /* !CONFIG_FILE_LOCKING */
 
 
index be342b9..63ca8da 100644 (file)
 #define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
 #define ___config_enabled(__ignored, val, ...) val
 
-/*
- * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
- * 0 otherwise.
- *
- */
-#define IS_ENABLED(option) \
-       (config_enabled(option) || config_enabled(option##_MODULE))
-
 /*
  * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
  * otherwise. For boolean options, this is equivalent to
  */
 #define IS_MODULE(option) config_enabled(option##_MODULE)
 
+/*
+ * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
+ * 0 otherwise.
+ */
+#define IS_ENABLED(option) \
+       (IS_BUILTIN(option) || IS_MODULE(option))
+
 #endif /* __LINUX_KCONFIG_H */
index d6d630d..3a5b48e 100644 (file)
                (((__x) - ((__d) / 2)) / (__d));        \
 }                                                      \
 )
+/*
+ * Same as above but for u64 dividends. divisor must be a 32-bit
+ * number.
+ */
+#define DIV_ROUND_CLOSEST_ULL(x, divisor)(             \
+{                                                      \
+       typeof(divisor) __d = divisor;                  \
+       unsigned long long _tmp = (x) + (__d) / 2;      \
+       do_div(_tmp, __d);                              \
+       _tmp;                                           \
+}                                                      \
+)
 
 /*
  * Multiplies an integer by a fraction, while avoiding unnecessary
index b6401e7..29c30ac 100644 (file)
@@ -105,6 +105,8 @@ enum s2mps_rtc_reg {
 #define S5M_RTC_UDR_MASK       (1 << S5M_RTC_UDR_SHIFT)
 #define S2MPS_RTC_WUDR_SHIFT   4
 #define S2MPS_RTC_WUDR_MASK    (1 << S2MPS_RTC_WUDR_SHIFT)
+#define S2MPS13_RTC_AUDR_SHIFT 1
+#define S2MPS13_RTC_AUDR_MASK  (1 << S2MPS13_RTC_AUDR_SHIFT)
 #define S2MPS_RTC_RUDR_SHIFT   0
 #define S2MPS_RTC_RUDR_MASK    (1 << S2MPS_RTC_RUDR_SHIFT)
 #define RTC_TCON_SHIFT         1
index 590630e..8d37e26 100644 (file)
@@ -429,7 +429,7 @@ struct mm_struct {
 #endif
 
        /* store ref to file /proc/<pid>/exe symlink points to */
-       struct file *exe_file;
+       struct file __rcu *exe_file;
 #ifdef CONFIG_MMU_NOTIFIER
        struct mmu_notifier_mm *mmu_notifier_mm;
 #endif
index b7361f8..795d5fe 100644 (file)
@@ -212,4 +212,7 @@ static inline void setup_sysctl_set(struct ctl_table_set *p,
 
 #endif /* CONFIG_SYSCTL */
 
+int sysctl_max_threads(struct ctl_table *table, int write,
+                      void __user *buffer, size_t *lenp, loff_t *ppos);
+
 #endif /* _LINUX_SYSCTL_H */
diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h
new file mode 100644 (file)
index 0000000..d5f4fb6
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _LINUX_HELPER_MACROS_H_
+#define _LINUX_HELPER_MACROS_H_
+
+#define __find_closest(x, a, as, op)                                   \
+({                                                                     \
+       typeof(as) __fc_i, __fc_as = (as) - 1;                          \
+       typeof(x) __fc_x = (x);                                         \
+       typeof(*a) *__fc_a = (a);                                       \
+       for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) {                  \
+               if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] +        \
+                                               __fc_a[__fc_i + 1], 2)) \
+                       break;                                          \
+       }                                                               \
+       (__fc_i);                                                       \
+})
+
+/**
+ * find_closest - locate the closest element in a sorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element. Must be sorted
+ *  in ascending order.
+ * @as: Size of 'a'.
+ *
+ * Returns the index of the element closest to 'x'.
+ */
+#define find_closest(x, a, as) __find_closest(x, a, as, <=)
+
+/**
+ * find_closest_descending - locate the closest element in a sorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element. Must be sorted
+ *  in descending order.
+ * @as: Size of 'a'.
+ *
+ * Similar to find_closest() but 'a' is expected to be sorted in descending
+ * order.
+ */
+#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
+
+#endif
index 1e1ea6e..88e0914 100644 (file)
@@ -6,7 +6,16 @@
 #define        EDEADLK         35      /* Resource deadlock would occur */
 #define        ENAMETOOLONG    36      /* File name too long */
 #define        ENOLCK          37      /* No record locks available */
-#define        ENOSYS          38      /* Function not implemented */
+
+/*
+ * This error code is special: arch syscall entry code will return
+ * -ENOSYS if users try to call a syscall that doesn't exist.  To keep
+ * failures of syscalls that really do exist distinguishable from
+ * failures due to attempts to use a nonexistent syscall, syscall
+ * implementations should refrain from returning -ENOSYS.
+ */
+#define        ENOSYS          38      /* Invalid system call number */
+
 #define        ENOTEMPTY       39      /* Directory not empty */
 #define        ELOOP           40      /* Too many symbolic links encountered */
 #define        EWOULDBLOCK     EAGAIN  /* Operation would block */
index a7e969d..2115055 100644 (file)
@@ -91,7 +91,7 @@
 static int kernel_init(void *);
 
 extern void init_IRQ(void);
-extern void fork_init(unsigned long);
+extern void fork_init(void);
 extern void radix_tree_init(void);
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
@@ -645,7 +645,7 @@ asmlinkage __visible void __init start_kernel(void)
 #endif
        thread_info_cache_init();
        cred_init();
-       fork_init(totalram_pages);
+       fork_init();
        proc_caches_init();
        buffer_init();
        key_init();
index f2c1e73..03c1eaa 100644 (file)
@@ -74,6 +74,7 @@
 #include <linux/uprobes.h>
 #include <linux/aio.h>
 #include <linux/compiler.h>
+#include <linux/sysctl.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/task.h>
 
+/*
+ * Minimum number of threads to boot the kernel
+ */
+#define MIN_THREADS 20
+
+/*
+ * Maximum number of threads
+ */
+#define MAX_THREADS FUTEX_TID_MASK
+
 /*
  * Protected counters by write_lock_irq(&tasklist_lock)
  */
@@ -253,7 +264,30 @@ EXPORT_SYMBOL_GPL(__put_task_struct);
 
 void __init __weak arch_task_cache_init(void) { }
 
-void __init fork_init(unsigned long mempages)
+/*
+ * set_max_threads
+ */
+static void set_max_threads(unsigned int max_threads_suggested)
+{
+       u64 threads;
+
+       /*
+        * The number of threads shall be limited such that the thread
+        * structures may only consume a small part of the available memory.
+        */
+       if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64)
+               threads = MAX_THREADS;
+       else
+               threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE,
+                                   (u64) THREAD_SIZE * 8UL);
+
+       if (threads > max_threads_suggested)
+               threads = max_threads_suggested;
+
+       max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS);
+}
+
+void __init fork_init(void)
 {
 #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
 #ifndef ARCH_MIN_TASKALIGN
@@ -268,18 +302,7 @@ void __init fork_init(unsigned long mempages)
        /* do the arch specific task caches init */
        arch_task_cache_init();
 
-       /*
-        * The default maximum number of threads is set to a safe
-        * value: the thread structures can take up at most half
-        * of memory.
-        */
-       max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
-
-       /*
-        * we need to allow at least 20 threads to boot a system
-        */
-       if (max_threads < 20)
-               max_threads = 20;
+       set_max_threads(MAX_THREADS);
 
        init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
        init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
@@ -380,6 +403,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
         */
        down_write_nested(&mm->mmap_sem, SINGLE_DEPTH_NESTING);
 
+       /* No ordering required: file already has been exposed. */
+       RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));
+
        mm->total_vm = oldmm->total_vm;
        mm->shared_vm = oldmm->shared_vm;
        mm->exec_vm = oldmm->exec_vm;
@@ -505,7 +531,13 @@ static inline void mm_free_pgd(struct mm_struct *mm)
        pgd_free(mm, mm->pgd);
 }
 #else
-#define dup_mmap(mm, oldmm)    (0)
+static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+{
+       down_write(&oldmm->mmap_sem);
+       RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));
+       up_write(&oldmm->mmap_sem);
+       return 0;
+}
 #define mm_alloc_pgd(mm)       (0)
 #define mm_free_pgd(mm)
 #endif /* CONFIG_MMU */
@@ -674,34 +706,53 @@ void mmput(struct mm_struct *mm)
 }
 EXPORT_SYMBOL_GPL(mmput);
 
+/**
+ * set_mm_exe_file - change a reference to the mm's executable file
+ *
+ * This changes mm's executable file (shown as symlink /proc/[pid]/exe).
+ *
+ * Main users are mmput() and sys_execve(). Callers prevent concurrent
+ * invocations: in mmput() nobody alive left, in execve task is single
+ * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the
+ * mm->exe_file, but does so without using set_mm_exe_file() in order
+ * to do avoid the need for any locks.
+ */
 void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
 {
+       struct file *old_exe_file;
+
+       /*
+        * It is safe to dereference the exe_file without RCU as
+        * this function is only called if nobody else can access
+        * this mm -- see comment above for justification.
+        */
+       old_exe_file = rcu_dereference_raw(mm->exe_file);
+
        if (new_exe_file)
                get_file(new_exe_file);
-       if (mm->exe_file)
-               fput(mm->exe_file);
-       mm->exe_file = new_exe_file;
+       rcu_assign_pointer(mm->exe_file, new_exe_file);
+       if (old_exe_file)
+               fput(old_exe_file);
 }
 
+/**
+ * get_mm_exe_file - acquire a reference to the mm's executable file
+ *
+ * Returns %NULL if mm has no associated executable file.
+ * User must release file via fput().
+ */
 struct file *get_mm_exe_file(struct mm_struct *mm)
 {
        struct file *exe_file;
 
-       /* We need mmap_sem to protect against races with removal of exe_file */
-       down_read(&mm->mmap_sem);
-       exe_file = mm->exe_file;
-       if (exe_file)
-               get_file(exe_file);
-       up_read(&mm->mmap_sem);
+       rcu_read_lock();
+       exe_file = rcu_dereference(mm->exe_file);
+       if (exe_file && !get_file_rcu(exe_file))
+               exe_file = NULL;
+       rcu_read_unlock();
        return exe_file;
 }
-
-static void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm)
-{
-       /* It's safe to write the exe_file pointer without exe_file_lock because
-        * this is called during fork when the task is not yet in /proc */
-       newmm->exe_file = get_mm_exe_file(oldmm);
-}
+EXPORT_SYMBOL(get_mm_exe_file);
 
 /**
  * get_task_mm - acquire a reference to the task's mm
@@ -864,8 +915,6 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
        if (!mm_init(mm, tsk))
                goto fail_nomem;
 
-       dup_mm_exe_file(oldmm, mm);
-
        err = dup_mmap(mm, oldmm);
        if (err)
                goto free_pt;
@@ -1403,10 +1452,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                goto bad_fork_cleanup_io;
 
        if (pid != &init_struct_pid) {
-               retval = -ENOMEM;
                pid = alloc_pid(p->nsproxy->pid_ns_for_children);
-               if (!pid)
+               if (IS_ERR(pid)) {
+                       retval = PTR_ERR(pid);
                        goto bad_fork_cleanup_io;
+               }
        }
 
        p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
@@ -2000,3 +2050,26 @@ int unshare_files(struct files_struct **displaced)
        task_unlock(task);
        return 0;
 }
+
+int sysctl_max_threads(struct ctl_table *table, int write,
+                      void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table t;
+       int ret;
+       int threads = max_threads;
+       int min = MIN_THREADS;
+       int max = MAX_THREADS;
+
+       t = *table;
+       t.data = &threads;
+       t.extra1 = &min;
+       t.extra2 = &max;
+
+       ret = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
+       if (ret || !write)
+               return ret;
+
+       set_max_threads(threads);
+
+       return 0;
+}
index b358a80..a744098 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 #include "gcov.h"
 
 static int gcov_events_enabled;
@@ -107,8 +108,10 @@ void gcov_enable_events(void)
        gcov_events_enabled = 1;
 
        /* Perform event callback for previously registered entries. */
-       while ((info = gcov_info_next(info)))
+       while ((info = gcov_info_next(info))) {
                gcov_event(GCOV_ADD, info);
+               cond_resched();
+       }
 
        mutex_unlock(&gcov_lock);
 }
index cd36a5e..4fd07d5 100644 (file)
@@ -182,7 +182,7 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
                        spin_unlock_irq(&pidmap_lock);
                        kfree(page);
                        if (unlikely(!map->page))
-                               break;
+                               return -ENOMEM;
                }
                if (likely(atomic_read(&map->nr_free))) {
                        for ( ; ; ) {
@@ -210,7 +210,7 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
                }
                pid = mk_pid(pid_ns, map, offset);
        }
-       return -1;
+       return -EAGAIN;
 }
 
 int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
@@ -301,17 +301,20 @@ struct pid *alloc_pid(struct pid_namespace *ns)
        int i, nr;
        struct pid_namespace *tmp;
        struct upid *upid;
+       int retval = -ENOMEM;
 
        pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
        if (!pid)
-               goto out;
+               return ERR_PTR(retval);
 
        tmp = ns;
        pid->level = ns->level;
        for (i = ns->level; i >= 0; i--) {
                nr = alloc_pidmap(tmp);
-               if (nr < 0)
+               if (IS_ERR_VALUE(nr)) {
+                       retval = nr;
                        goto out_free;
+               }
 
                pid->numbers[i].nr = nr;
                pid->numbers[i].ns = tmp;
@@ -339,7 +342,6 @@ struct pid *alloc_pid(struct pid_namespace *ns)
        }
        spin_unlock_irq(&pidmap_lock);
 
-out:
        return pid;
 
 out_unlock:
@@ -351,8 +353,7 @@ out_free:
                free_pidmap(pid->numbers + i);
 
        kmem_cache_free(ns->pid_cachep, pid);
-       pid = NULL;
-       goto out;
+       return ERR_PTR(retval);
 }
 
 void disable_pid_allocation(struct pid_namespace *ns)
index 227fec3..c8e0e05 100644 (file)
@@ -456,8 +456,6 @@ static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
 
 static int ptrace_detach(struct task_struct *child, unsigned int data)
 {
-       bool dead = false;
-
        if (!valid_signal(data))
                return -EIO;
 
@@ -467,18 +465,19 @@ static int ptrace_detach(struct task_struct *child, unsigned int data)
 
        write_lock_irq(&tasklist_lock);
        /*
-        * This child can be already killed. Make sure de_thread() or
-        * our sub-thread doing do_wait() didn't do release_task() yet.
+        * We rely on ptrace_freeze_traced(). It can't be killed and
+        * untraced by another thread, it can't be a zombie.
         */
-       if (child->ptrace) {
-               child->exit_code = data;
-               dead = __ptrace_detach(current, child);
-       }
+       WARN_ON(!child->ptrace || child->exit_state);
+       /*
+        * tasklist_lock avoids the race with wait_task_stopped(), see
+        * the comment in ptrace_resume().
+        */
+       child->exit_code = data;
+       __ptrace_detach(current, child);
        write_unlock_irq(&tasklist_lock);
 
        proc_ptrace_connector(child, PTRACE_DETACH);
-       if (unlikely(dead))
-               release_task(child);
 
        return 0;
 }
@@ -697,6 +696,8 @@ static int ptrace_peek_siginfo(struct task_struct *child,
 static int ptrace_resume(struct task_struct *child, long request,
                         unsigned long data)
 {
+       bool need_siglock;
+
        if (!valid_signal(data))
                return -EIO;
 
@@ -724,8 +725,26 @@ static int ptrace_resume(struct task_struct *child, long request,
                user_disable_single_step(child);
        }
 
+       /*
+        * Change ->exit_code and ->state under siglock to avoid the race
+        * with wait_task_stopped() in between; a non-zero ->exit_code will
+        * wrongly look like another report from tracee.
+        *
+        * Note that we need siglock even if ->exit_code == data and/or this
+        * status was not reported yet, the new status must not be cleared by
+        * wait_task_stopped() after resume.
+        *
+        * If data == 0 we do not care if wait_task_stopped() reports the old
+        * status and clears the code too; this can't race with the tracee, it
+        * takes siglock after resume.
+        */
+       need_siglock = data && !thread_group_empty(current);
+       if (need_siglock)
+               spin_lock_irq(&child->sighand->siglock);
        child->exit_code = data;
        wake_up_state(child, __TASK_TRACED);
+       if (need_siglock)
+               spin_unlock_irq(&child->sighand->siglock);
 
        return 0;
 }
index a390499..d51c5dd 100644 (file)
@@ -2992,11 +2992,9 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
         * Nor can they impersonate a kill()/tgkill(), which adds source info.
         */
        if ((info->si_code >= 0 || info->si_code == SI_TKILL) &&
-           (task_pid_vnr(current) != pid)) {
-               /* We used to allow any < 0 si_code */
-               WARN_ON_ONCE(info->si_code < 0);
+           (task_pid_vnr(current) != pid))
                return -EPERM;
-       }
+
        info->si_signo = sig;
 
        /* POSIX.1b doesn't mention process groups.  */
@@ -3041,12 +3039,10 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
        /* Not even root can pretend to send signals from the kernel.
         * Nor can they impersonate a kill()/tgkill(), which adds source info.
         */
-       if (((info->si_code >= 0 || info->si_code == SI_TKILL)) &&
-           (task_pid_vnr(current) != pid)) {
-               /* We used to allow any < 0 si_code */
-               WARN_ON_ONCE(info->si_code < 0);
+       if ((info->si_code >= 0 || info->si_code == SI_TKILL) &&
+           (task_pid_vnr(current) != pid))
                return -EPERM;
-       }
+
        info->si_signo = sig;
 
        return do_send_specific(tgid, pid, sig, info);
index 3be3449..a4e372b 100644 (file)
@@ -1649,14 +1649,13 @@ SYSCALL_DEFINE1(umask, int, mask)
        return mask;
 }
 
-static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd)
+static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 {
        struct fd exe;
+       struct file *old_exe, *exe_file;
        struct inode *inode;
        int err;
 
-       VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm);
-
        exe = fdget(fd);
        if (!exe.file)
                return -EBADF;
@@ -1680,15 +1679,22 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd)
        /*
         * Forbid mm->exe_file change if old file still mapped.
         */
+       exe_file = get_mm_exe_file(mm);
        err = -EBUSY;
-       if (mm->exe_file) {
+       if (exe_file) {
                struct vm_area_struct *vma;
 
-               for (vma = mm->mmap; vma; vma = vma->vm_next)
-                       if (vma->vm_file &&
-                           path_equal(&vma->vm_file->f_path,
-                                      &mm->exe_file->f_path))
-                               goto exit;
+               down_read(&mm->mmap_sem);
+               for (vma = mm->mmap; vma; vma = vma->vm_next) {
+                       if (!vma->vm_file)
+                               continue;
+                       if (path_equal(&vma->vm_file->f_path,
+                                      &exe_file->f_path))
+                               goto exit_err;
+               }
+
+               up_read(&mm->mmap_sem);
+               fput(exe_file);
        }
 
        /*
@@ -1702,10 +1708,18 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd)
                goto exit;
 
        err = 0;
-       set_mm_exe_file(mm, exe.file);  /* this grabs a reference to exe.file */
+       /* set the new file, lockless */
+       get_file(exe.file);
+       old_exe = xchg(&mm->exe_file, exe.file);
+       if (old_exe)
+               fput(old_exe);
 exit:
        fdput(exe);
        return err;
+exit_err:
+       up_read(&mm->mmap_sem);
+       fput(exe_file);
+       goto exit;
 }
 
 #ifdef CONFIG_CHECKPOINT_RESTORE
@@ -1840,10 +1854,9 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
                user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL;
        }
 
-       down_write(&mm->mmap_sem);
        if (prctl_map.exe_fd != (u32)-1)
-               error = prctl_set_mm_exe_file_locked(mm, prctl_map.exe_fd);
-       downgrade_write(&mm->mmap_sem);
+               error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd);
+       down_read(&mm->mmap_sem);
        if (error)
                goto out;
 
@@ -1909,12 +1922,8 @@ static int prctl_set_mm(int opt, unsigned long addr,
        if (!capable(CAP_SYS_RESOURCE))
                return -EPERM;
 
-       if (opt == PR_SET_MM_EXE_FILE) {
-               down_write(&mm->mmap_sem);
-               error = prctl_set_mm_exe_file_locked(mm, (unsigned int)addr);
-               up_write(&mm->mmap_sem);
-               return error;
-       }
+       if (opt == PR_SET_MM_EXE_FILE)
+               return prctl_set_mm_exe_file(mm, (unsigned int)addr);
 
        if (addr >= TASK_SIZE || addr < mmap_min_addr)
                return -EINVAL;
index 42b7fc2..2082b1a 100644 (file)
 #include <linux/nmi.h>
 #endif
 
-
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
-extern int max_threads;
 extern int suid_dumpable;
 #ifdef CONFIG_COREDUMP
 extern int core_uses_pid;
@@ -710,10 +708,10 @@ static struct ctl_table kern_table[] = {
 #endif
        {
                .procname       = "threads-max",
-               .data           = &max_threads,
+               .data           = NULL,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = sysctl_max_threads,
        },
        {
                .procname       = "random",
@@ -1983,7 +1981,15 @@ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
                                 int write, void *data)
 {
        if (write) {
-               *valp = *negp ? -*lvalp : *lvalp;
+               if (*negp) {
+                       if (*lvalp > (unsigned long) INT_MAX + 1)
+                               return -EINVAL;
+                       *valp = -*lvalp;
+               } else {
+                       if (*lvalp > (unsigned long) INT_MAX)
+                               return -EINVAL;
+                       *valp = *lvalp;
+               }
        } else {
                int val = *valp;
                if (val < 0) {
index 87da53b..f544022 100644 (file)
@@ -18,9 +18,8 @@ config HAVE_ARCH_BITREVERSE
        default n
        depends on BITREVERSE
        help
-         This option provides an config for the architecture which have instruction
-         can do bitreverse operation, we use the hardware instruction if the architecture
-         have this capability.
+         This option enables the use of hardware bit-reversal instructions on
+         architectures which support such operations.
 
 config RATIONAL
        bool
index 58f74d2..da6116b 100644 (file)
@@ -25,7 +25,7 @@ obj-y += lockref.o
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
         gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \
-        bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
+        bsearch.o find_bit.o llist.o memweight.o kfifo.o \
         percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
index d456f4c..64c0926 100644 (file)
  * for the best explanations of this ordering.
  */
 
-int __bitmap_empty(const unsigned long *bitmap, unsigned int bits)
-{
-       unsigned int k, lim = bits/BITS_PER_LONG;
-       for (k = 0; k < lim; ++k)
-               if (bitmap[k])
-                       return 0;
-
-       if (bits % BITS_PER_LONG)
-               if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
-                       return 0;
-
-       return 1;
-}
-EXPORT_SYMBOL(__bitmap_empty);
-
-int __bitmap_full(const unsigned long *bitmap, unsigned int bits)
-{
-       unsigned int k, lim = bits/BITS_PER_LONG;
-       for (k = 0; k < lim; ++k)
-               if (~bitmap[k])
-                       return 0;
-
-       if (bits % BITS_PER_LONG)
-               if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
-                       return 0;
-
-       return 1;
-}
-EXPORT_SYMBOL(__bitmap_full);
-
 int __bitmap_equal(const unsigned long *bitmap1,
                const unsigned long *bitmap2, unsigned int bits)
 {
index b6513a9..5ab1553 100644 (file)
@@ -37,10 +37,11 @@ EXPORT_SYMBOL(__next_cpu_nr);
 int cpumask_next_and(int n, const struct cpumask *src1p,
                     const struct cpumask *src2p)
 {
-       while ((n = cpumask_next(n, src1p)) < nr_cpu_ids)
-               if (cpumask_test_cpu(n, src2p))
-                       break;
-       return n;
+       struct cpumask tmp;
+
+       if (cpumask_and(&tmp, src1p, src2p))
+               return cpumask_next(n, &tmp);
+       return nr_cpu_ids;
 }
 EXPORT_SYMBOL(cpumask_next_and);
 
index 9722bd2..ae4b65e 100644 (file)
@@ -361,7 +361,7 @@ static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket,
        unsigned int range = 0;
 
        while (range <= max_range) {
-               entry = __hash_bucket_find(*bucket, &index, containing_match);
+               entry = __hash_bucket_find(*bucket, ref, containing_match);
 
                if (entry)
                        return entry;
diff --git a/lib/find_bit.c b/lib/find_bit.c
new file mode 100644 (file)
index 0000000..18072ea
--- /dev/null
@@ -0,0 +1,193 @@
+/* bit search implementation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Copyright (C) 2008 IBM Corporation
+ * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
+ * (Inspired by David Howell's find_next_bit implementation)
+ *
+ * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
+ * size and improve performance, 2015.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bitmap.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+
+#if !defined(find_next_bit) || !defined(find_next_zero_bit)
+
+/*
+ * This is a common helper function for find_next_bit and
+ * find_next_zero_bit.  The difference is the "invert" argument, which
+ * is XORed with each fetched word before searching it for one bits.
+ */
+static unsigned long _find_next_bit(const unsigned long *addr,
+               unsigned long nbits, unsigned long start, unsigned long invert)
+{
+       unsigned long tmp;
+
+       if (!nbits || start >= nbits)
+               return nbits;
+
+       tmp = addr[start / BITS_PER_LONG] ^ invert;
+
+       /* Handle 1st word. */
+       tmp &= BITMAP_FIRST_WORD_MASK(start);
+       start = round_down(start, BITS_PER_LONG);
+
+       while (!tmp) {
+               start += BITS_PER_LONG;
+               if (start >= nbits)
+                       return nbits;
+
+               tmp = addr[start / BITS_PER_LONG] ^ invert;
+       }
+
+       return min(start + __ffs(tmp), nbits);
+}
+#endif
+
+#ifndef find_next_bit
+/*
+ * Find the next set bit in a memory region.
+ */
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+                           unsigned long offset)
+{
+       return _find_next_bit(addr, size, offset, 0UL);
+}
+EXPORT_SYMBOL(find_next_bit);
+#endif
+
+#ifndef find_next_zero_bit
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+                                unsigned long offset)
+{
+       return _find_next_bit(addr, size, offset, ~0UL);
+}
+EXPORT_SYMBOL(find_next_zero_bit);
+#endif
+
+#ifndef find_first_bit
+/*
+ * Find the first set bit in a memory region.
+ */
+unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
+{
+       unsigned long idx;
+
+       for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
+               if (addr[idx])
+                       return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
+       }
+
+       return size;
+}
+EXPORT_SYMBOL(find_first_bit);
+#endif
+
+#ifndef find_first_zero_bit
+/*
+ * Find the first cleared bit in a memory region.
+ */
+unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
+{
+       unsigned long idx;
+
+       for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
+               if (addr[idx] != ~0UL)
+                       return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
+       }
+
+       return size;
+}
+EXPORT_SYMBOL(find_first_zero_bit);
+#endif
+
+#ifndef find_last_bit
+unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
+{
+       if (size) {
+               unsigned long val = BITMAP_LAST_WORD_MASK(size);
+               unsigned long idx = (size-1) / BITS_PER_LONG;
+
+               do {
+                       val &= addr[idx];
+                       if (val)
+                               return idx * BITS_PER_LONG + __fls(val);
+
+                       val = ~0ul;
+               } while (idx--);
+       }
+       return size;
+}
+EXPORT_SYMBOL(find_last_bit);
+#endif
+
+#ifdef __BIG_ENDIAN
+
+/* include/linux/byteorder does not support "unsigned long" type */
+static inline unsigned long ext2_swab(const unsigned long y)
+{
+#if BITS_PER_LONG == 64
+       return (unsigned long) __swab64((u64) y);
+#elif BITS_PER_LONG == 32
+       return (unsigned long) __swab32((u32) y);
+#else
+#error BITS_PER_LONG not defined
+#endif
+}
+
+#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
+static unsigned long _find_next_bit_le(const unsigned long *addr,
+               unsigned long nbits, unsigned long start, unsigned long invert)
+{
+       unsigned long tmp;
+
+       if (!nbits || start >= nbits)
+               return nbits;
+
+       tmp = addr[start / BITS_PER_LONG] ^ invert;
+
+       /* Handle 1st word. */
+       tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
+       start = round_down(start, BITS_PER_LONG);
+
+       while (!tmp) {
+               start += BITS_PER_LONG;
+               if (start >= nbits)
+                       return nbits;
+
+               tmp = addr[start / BITS_PER_LONG] ^ invert;
+       }
+
+       return min(start + __ffs(ext2_swab(tmp)), nbits);
+}
+#endif
+
+#ifndef find_next_zero_bit_le
+unsigned long find_next_zero_bit_le(const void *addr, unsigned
+               long size, unsigned long offset)
+{
+       return _find_next_bit_le(addr, size, offset, ~0UL);
+}
+EXPORT_SYMBOL(find_next_zero_bit_le);
+#endif
+
+#ifndef find_next_bit_le
+unsigned long find_next_bit_le(const void *addr, unsigned
+               long size, unsigned long offset)
+{
+       return _find_next_bit_le(addr, size, offset, 0UL);
+}
+EXPORT_SYMBOL(find_next_bit_le);
+#endif
+
+#endif /* __BIG_ENDIAN */
index 91ca09f..3e3be40 100644 (file)
@@ -4,6 +4,9 @@
  * Written by Rusty Russell <rusty@rustcorp.com.au>
  * (Inspired by David Howell's find_next_bit implementation)
  *
+ * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
+ * size and improve performance, 2015.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
  */
 
 #include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/export.h>
-#include <asm/types.h>
-#include <asm/byteorder.h>
+#include <linux/kernel.h>
 
 #ifndef find_last_bit
 
 unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
 {
-       unsigned long words;
-       unsigned long tmp;
-
-       /* Start at final word. */
-       words = size / BITS_PER_LONG;
+       if (size) {
+               unsigned long val = BITMAP_LAST_WORD_MASK(size);
+               unsigned long idx = (size-1) / BITS_PER_LONG;
 
-       /* Partial final word? */
-       if (size & (BITS_PER_LONG-1)) {
-               tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
-                                        - (size & (BITS_PER_LONG-1)))));
-               if (tmp)
-                       goto found;
-       }
+               do {
+                       val &= addr[idx];
+                       if (val)
+                               return idx * BITS_PER_LONG + __fls(val);
 
-       while (words) {
-               tmp = addr[--words];
-               if (tmp) {
-found:
-                       return words * BITS_PER_LONG + __fls(tmp);
-               }
+                       val = ~0ul;
+               } while (idx--);
        }
-
-       /* Not found */
        return size;
 }
 EXPORT_SYMBOL(find_last_bit);
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
deleted file mode 100644 (file)
index 0cbfc0b..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/* find_next_bit.c: fallback find next bit implementation
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/bitops.h>
-#include <linux/export.h>
-#include <asm/types.h>
-#include <asm/byteorder.h>
-
-#define BITOP_WORD(nr)         ((nr) / BITS_PER_LONG)
-
-#ifndef find_next_bit
-/*
- * Find the next set bit in a memory region.
- */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
-                           unsigned long offset)
-{
-       const unsigned long *p = addr + BITOP_WORD(offset);
-       unsigned long result = offset & ~(BITS_PER_LONG-1);
-       unsigned long tmp;
-
-       if (offset >= size)
-               return size;
-       size -= result;
-       offset %= BITS_PER_LONG;
-       if (offset) {
-               tmp = *(p++);
-               tmp &= (~0UL << offset);
-               if (size < BITS_PER_LONG)
-                       goto found_first;
-               if (tmp)
-                       goto found_middle;
-               size -= BITS_PER_LONG;
-               result += BITS_PER_LONG;
-       }
-       while (size & ~(BITS_PER_LONG-1)) {
-               if ((tmp = *(p++)))
-                       goto found_middle;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-       tmp = *p;
-
-found_first:
-       tmp &= (~0UL >> (BITS_PER_LONG - size));
-       if (tmp == 0UL)         /* Are any bits set? */
-               return result + size;   /* Nope. */
-found_middle:
-       return result + __ffs(tmp);
-}
-EXPORT_SYMBOL(find_next_bit);
-#endif
-
-#ifndef find_next_zero_bit
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-                                unsigned long offset)
-{
-       const unsigned long *p = addr + BITOP_WORD(offset);
-       unsigned long result = offset & ~(BITS_PER_LONG-1);
-       unsigned long tmp;
-
-       if (offset >= size)
-               return size;
-       size -= result;
-       offset %= BITS_PER_LONG;
-       if (offset) {
-               tmp = *(p++);
-               tmp |= ~0UL >> (BITS_PER_LONG - offset);
-               if (size < BITS_PER_LONG)
-                       goto found_first;
-               if (~tmp)
-                       goto found_middle;
-               size -= BITS_PER_LONG;
-               result += BITS_PER_LONG;
-       }
-       while (size & ~(BITS_PER_LONG-1)) {
-               if (~(tmp = *(p++)))
-                       goto found_middle;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-       tmp = *p;
-
-found_first:
-       tmp |= ~0UL << size;
-       if (tmp == ~0UL)        /* Are any bits zero? */
-               return result + size;   /* Nope. */
-found_middle:
-       return result + ffz(tmp);
-}
-EXPORT_SYMBOL(find_next_zero_bit);
-#endif
-
-#ifndef find_first_bit
-/*
- * Find the first set bit in a memory region.
- */
-unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
-{
-       const unsigned long *p = addr;
-       unsigned long result = 0;
-       unsigned long tmp;
-
-       while (size & ~(BITS_PER_LONG-1)) {
-               if ((tmp = *(p++)))
-                       goto found;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-
-       tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
-       if (tmp == 0UL)         /* Are any bits set? */
-               return result + size;   /* Nope. */
-found:
-       return result + __ffs(tmp);
-}
-EXPORT_SYMBOL(find_first_bit);
-#endif
-
-#ifndef find_first_zero_bit
-/*
- * Find the first cleared bit in a memory region.
- */
-unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
-{
-       const unsigned long *p = addr;
-       unsigned long result = 0;
-       unsigned long tmp;
-
-       while (size & ~(BITS_PER_LONG-1)) {
-               if (~(tmp = *(p++)))
-                       goto found;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-
-       tmp = (*p) | (~0UL << size);
-       if (tmp == ~0UL)        /* Are any bits zero? */
-               return result + size;   /* Nope. */
-found:
-       return result + ffz(tmp);
-}
-EXPORT_SYMBOL(find_first_zero_bit);
-#endif
-
-#ifdef __BIG_ENDIAN
-
-/* include/linux/byteorder does not support "unsigned long" type */
-static inline unsigned long ext2_swabp(const unsigned long * x)
-{
-#if BITS_PER_LONG == 64
-       return (unsigned long) __swab64p((u64 *) x);
-#elif BITS_PER_LONG == 32
-       return (unsigned long) __swab32p((u32 *) x);
-#else
-#error BITS_PER_LONG not defined
-#endif
-}
-
-/* include/linux/byteorder doesn't support "unsigned long" type */
-static inline unsigned long ext2_swab(const unsigned long y)
-{
-#if BITS_PER_LONG == 64
-       return (unsigned long) __swab64((u64) y);
-#elif BITS_PER_LONG == 32
-       return (unsigned long) __swab32((u32) y);
-#else
-#error BITS_PER_LONG not defined
-#endif
-}
-
-#ifndef find_next_zero_bit_le
-unsigned long find_next_zero_bit_le(const void *addr, unsigned
-               long size, unsigned long offset)
-{
-       const unsigned long *p = addr;
-       unsigned long result = offset & ~(BITS_PER_LONG - 1);
-       unsigned long tmp;
-
-       if (offset >= size)
-               return size;
-       p += BITOP_WORD(offset);
-       size -= result;
-       offset &= (BITS_PER_LONG - 1UL);
-       if (offset) {
-               tmp = ext2_swabp(p++);
-               tmp |= (~0UL >> (BITS_PER_LONG - offset));
-               if (size < BITS_PER_LONG)
-                       goto found_first;
-               if (~tmp)
-                       goto found_middle;
-               size -= BITS_PER_LONG;
-               result += BITS_PER_LONG;
-       }
-
-       while (size & ~(BITS_PER_LONG - 1)) {
-               if (~(tmp = *(p++)))
-                       goto found_middle_swap;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-       tmp = ext2_swabp(p);
-found_first:
-       tmp |= ~0UL << size;
-       if (tmp == ~0UL)        /* Are any bits zero? */
-               return result + size; /* Nope. Skip ffz */
-found_middle:
-       return result + ffz(tmp);
-
-found_middle_swap:
-       return result + ffz(ext2_swab(tmp));
-}
-EXPORT_SYMBOL(find_next_zero_bit_le);
-#endif
-
-#ifndef find_next_bit_le
-unsigned long find_next_bit_le(const void *addr, unsigned
-               long size, unsigned long offset)
-{
-       const unsigned long *p = addr;
-       unsigned long result = offset & ~(BITS_PER_LONG - 1);
-       unsigned long tmp;
-
-       if (offset >= size)
-               return size;
-       p += BITOP_WORD(offset);
-       size -= result;
-       offset &= (BITS_PER_LONG - 1UL);
-       if (offset) {
-               tmp = ext2_swabp(p++);
-               tmp &= (~0UL << offset);
-               if (size < BITS_PER_LONG)
-                       goto found_first;
-               if (tmp)
-                       goto found_middle;
-               size -= BITS_PER_LONG;
-               result += BITS_PER_LONG;
-       }
-
-       while (size & ~(BITS_PER_LONG - 1)) {
-               tmp = *(p++);
-               if (tmp)
-                       goto found_middle_swap;
-               result += BITS_PER_LONG;
-               size -= BITS_PER_LONG;
-       }
-       if (!size)
-               return result;
-       tmp = ext2_swabp(p);
-found_first:
-       tmp &= (~0UL >> (BITS_PER_LONG - size));
-       if (tmp == 0UL)         /* Are any bits set? */
-               return result + size; /* Nope. */
-found_middle:
-       return result + __ffs(tmp);
-
-found_middle_swap:
-       return result + __ffs(ext2_swab(tmp));
-}
-EXPORT_SYMBOL(find_next_bit_le);
-#endif
-
-#endif /* __BIG_ENDIAN */
index 3a1e084..da39c60 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/sections.h>      /* for dereference_function_descriptor() */
+#include <asm/byteorder.h>     /* cpu_to_le16 */
 
 #include <linux/string_helpers.h>
 #include "kstrtox.h"
@@ -122,142 +123,145 @@ int skip_atoi(const char **s)
        return i;
 }
 
-/* Decimal conversion is by far the most typical, and is used
- * for /proc and /sys data. This directly impacts e.g. top performance
- * with many processes running. We optimize it for speed
- * using ideas described at <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
- * (with permission from the author, Douglas W. Jones).
+/*
+ * Decimal conversion is by far the most typical, and is used for
+ * /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed by emitting
+ * two characters at a time, using a 200 byte lookup table. This
+ * roughly halves the number of multiplications compared to computing
+ * the digits one at a time. Implementation strongly inspired by the
+ * previous version, which in turn used ideas described at
+ * <http://www.cs.uiowa.edu/~jones/bcd/divide.html> (with permission
+ * from the author, Douglas W. Jones).
+ *
+ * It turns out there is precisely one 26 bit fixed-point
+ * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32
+ * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual
+ * range happens to be somewhat larger (x <= 1073741898), but that's
+ * irrelevant for our purpose.
+ *
+ * For dividing a number in the range [10^4, 10^6-1] by 100, we still
+ * need a 32x32->64 bit multiply, so we simply use the same constant.
+ *
+ * For dividing a number in the range [100, 10^4-1] by 100, there are
+ * several options. The simplest is (x * 0x147b) >> 19, which is valid
+ * for all x <= 43698.
  */
 
-#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
-/* Formats correctly any integer in [0, 999999999] */
+static const u16 decpair[100] = {
+#define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)
+       _( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),
+       _(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),
+       _(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),
+       _(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),
+       _(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49),
+       _(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59),
+       _(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69),
+       _(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79),
+       _(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89),
+       _(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99),
+#undef _
+};
+
+/*
+ * This will print a single '0' even if r == 0, since we would
+ * immediately jump to out_r where two 0s would be written but only
+ * one of them accounted for in buf. This is needed by ip4_string
+ * below. All other callers pass a non-zero value of r.
+*/
 static noinline_for_stack
-char *put_dec_full9(char *buf, unsigned q)
+char *put_dec_trunc8(char *buf, unsigned r)
 {
-       unsigned r;
+       unsigned q;
 
-       /*
-        * Possible ways to approx. divide by 10
-        * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit)
-        * (x * 0xcccd) >> 19     x <      81920 (x < 262149 when 64-bit mul)
-        * (x * 0x6667) >> 18     x <      43699
-        * (x * 0x3334) >> 17     x <      16389
-        * (x * 0x199a) >> 16     x <      16389
-        * (x * 0x0ccd) >> 15     x <      16389
-        * (x * 0x0667) >> 14     x <       2739
-        * (x * 0x0334) >> 13     x <       1029
-        * (x * 0x019a) >> 12     x <       1029
-        * (x * 0x00cd) >> 11     x <       1029 shorter code than * 0x67 (on i386)
-        * (x * 0x0067) >> 10     x <        179
-        * (x * 0x0034) >>  9     x <         69 same
-        * (x * 0x001a) >>  8     x <         69 same
-        * (x * 0x000d) >>  7     x <         69 same, shortest code (on i386)
-        * (x * 0x0007) >>  6     x <         19
-        * See <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
-        */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 1 */
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 2 */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 3 */
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 4 */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 5 */
-       /* Now value is under 10000, can avoid 64-bit multiply */
-       q      = (r * 0x199a) >> 16;
-       *buf++ = (r - 10 * q)  + '0'; /* 6 */
-       r      = (q * 0xcd) >> 11;
-       *buf++ = (q - 10 * r)  + '0'; /* 7 */
-       q      = (r * 0xcd) >> 11;
-       *buf++ = (r - 10 * q) + '0'; /* 8 */
-       *buf++ = q + '0'; /* 9 */
+       /* 1 <= r < 10^8 */
+       if (r < 100)
+               goto out_r;
+
+       /* 100 <= r < 10^8 */
+       q = (r * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+
+       /* 1 <= q < 10^6 */
+       if (q < 100)
+               goto out_q;
+
+       /*  100 <= q < 10^6 */
+       r = (q * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[q - 100*r];
+       buf += 2;
+
+       /* 1 <= r < 10^4 */
+       if (r < 100)
+               goto out_r;
+
+       /* 100 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+out_q:
+       /* 1 <= q < 100 */
+       r = q;
+out_r:
+       /* 1 <= r < 100 */
+       *((u16 *)buf) = decpair[r];
+       buf += r < 10 ? 1 : 2;
        return buf;
 }
-#endif
 
-/* Similar to above but do not pad with zeros.
- * Code can be easily arranged to print 9 digits too, but our callers
- * always call put_dec_full9() instead when the number has 9 decimal digits.
- */
+#if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64
 static noinline_for_stack
-char *put_dec_trunc8(char *buf, unsigned r)
+char *put_dec_full8(char *buf, unsigned r)
 {
        unsigned q;
 
-       /* Copy of previous function's body with added early returns */
-       while (r >= 10000) {
-               q = r + '0';
-               r  = (r * (uint64_t)0x1999999a) >> 32;
-               *buf++ = q - 10*r;
-       }
+       /* 0 <= r < 10^8 */
+       q = (r * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
 
-       q      = (r * 0x199a) >> 16;    /* r <= 9999 */
-       *buf++ = (r - 10 * q)  + '0';
-       if (q == 0)
-               return buf;
-       r      = (q * 0xcd) >> 11;      /* q <= 999 */
-       *buf++ = (q - 10 * r)  + '0';
-       if (r == 0)
-               return buf;
-       q      = (r * 0xcd) >> 11;      /* r <= 99 */
-       *buf++ = (r - 10 * q) + '0';
-       if (q == 0)
-               return buf;
-       *buf++ = q + '0';                /* q <= 9 */
-       return buf;
-}
+       /* 0 <= q < 10^6 */
+       r = (q * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[q - 100*r];
+       buf += 2;
 
-/* There are two algorithms to print larger numbers.
- * One is generic: divide by 1000000000 and repeatedly print
- * groups of (up to) 9 digits. It's conceptually simple,
- * but requires a (unsigned long long) / 1000000000 division.
- *
- * Second algorithm splits 64-bit unsigned long long into 16-bit chunks,
- * manipulates them cleverly and generates groups of 4 decimal digits.
- * It so happens that it does NOT require long long division.
- *
- * If long is > 32 bits, division of 64-bit values is relatively easy,
- * and we will use the first algorithm.
- * If long long is > 64 bits (strange architecture with VERY large long long),
- * second algorithm can't be used, and we again use the first one.
- *
- * Else (if long is 32 bits and long long is 64 bits) we use second one.
- */
+       /* 0 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
 
-#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
-
-/* First algorithm: generic */
+       /* 0 <= q < 100 */
+       *((u16 *)buf) = decpair[q];
+       buf += 2;
+       return buf;
+}
 
-static
+static noinline_for_stack
 char *put_dec(char *buf, unsigned long long n)
 {
-       if (n >= 100*1000*1000) {
-               while (n >= 1000*1000*1000)
-                       buf = put_dec_full9(buf, do_div(n, 1000*1000*1000));
-               if (n >= 100*1000*1000)
-                       return put_dec_full9(buf, n);
-       }
+       if (n >= 100*1000*1000)
+               buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
+       /* 1 <= n <= 1.6e11 */
+       if (n >= 100*1000*1000)
+               buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
+       /* 1 <= n < 1e8 */
        return put_dec_trunc8(buf, n);
 }
 
-#else
+#elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64
 
-/* Second algorithm: valid only for 64-bit long longs */
-
-/* See comment in put_dec_full9 for choice of constants */
-static noinline_for_stack
-void put_dec_full4(char *buf, unsigned q)
+static void
+put_dec_full4(char *buf, unsigned r)
 {
-       unsigned r;
-       r      = (q * 0xccd) >> 15;
-       buf[0] = (q - 10 * r) + '0';
-       q      = (r * 0xcd) >> 11;
-       buf[1] = (r - 10 * q)  + '0';
-       r      = (q * 0xcd) >> 11;
-       buf[2] = (q - 10 * r)  + '0';
-       buf[3] = r + '0';
+       unsigned q;
+
+       /* 0 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+       /* 0 <= q < 100 */
+       *((u16 *)buf) = decpair[q];
 }
 
 /*
@@ -265,9 +269,9 @@ void put_dec_full4(char *buf, unsigned q)
  * The approximation x/10000 == (x * 0x346DC5D7) >> 43
  * holds for all x < 1,128,869,999.  The largest value this
  * helper will ever be asked to convert is 1,125,520,955.
- * (d1 in the put_dec code, assuming n is all-ones).
+ * (second call in the put_dec code, assuming n is all-ones).
  */
-static
+static noinline_for_stack
 unsigned put_dec_helper4(char *buf, unsigned x)
 {
         uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
@@ -294,6 +298,8 @@ char *put_dec(char *buf, unsigned long long n)
        d2  = (h      ) & 0xffff;
        d3  = (h >> 16); /* implicit "& 0xffff" */
 
+       /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
+            = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
        q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
        q = put_dec_helper4(buf, q);
 
@@ -323,7 +329,8 @@ char *put_dec(char *buf, unsigned long long n)
  */
 int num_to_str(char *buf, int size, unsigned long long num)
 {
-       char tmp[sizeof(num) * 3];
+       /* put_dec requires 2-byte alignment of the buffer. */
+       char tmp[sizeof(num) * 3] __aligned(2);
        int idx, len;
 
        /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
@@ -384,7 +391,8 @@ static noinline_for_stack
 char *number(char *buf, char *end, unsigned long long num,
             struct printf_spec spec)
 {
-       char tmp[3 * sizeof(num)];
+       /* put_dec requires 2-byte alignment of the buffer. */
+       char tmp[3 * sizeof(num)] __aligned(2);
        char sign;
        char locase;
        int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
@@ -944,7 +952,7 @@ char *ip4_string(char *p, const u8 *addr, const char *fmt)
                break;
        }
        for (i = 0; i < 4; i++) {
-               char temp[3];   /* hold each IP quad in reverse order */
+               char temp[4] __aligned(2);      /* hold each IP quad in reverse order */
                int digits = put_dec_trunc8(temp, addr[index]) - temp;
                if (leading_zeros) {
                        if (digits < 3)
index 631619b..3f874d2 100644 (file)
@@ -13,12 +13,16 @@ CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
                --param asan-instrumentation-with-call-threshold=$(call_threshold))
 
 ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)
+   ifneq ($(CONFIG_COMPILE_TEST),y)
         $(warning Cannot use CONFIG_KASAN: \
             -fsanitize=kernel-address is not supported by compiler)
+   endif
 else
     ifeq ($(CFLAGS_KASAN),)
-        $(warning CONFIG_KASAN: compiler does not support all options.\
-            Trying minimal configuration)
+        ifneq ($(CONFIG_COMPILE_TEST),y)
+            $(warning CONFIG_KASAN: compiler does not support all options.\
+                Trying minimal configuration)
+        endif
         CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
     endif
 endif
index d124359..89b1df4 100755 (executable)
@@ -47,6 +47,8 @@ my $ignore_perl_version = 0;
 my $minimum_perl_version = 5.10.0;
 my $min_conf_desc_length = 4;
 my $spelling_file = "$D/spelling.txt";
+my $codespell = 0;
+my $codespellfile = "/usr/local/share/codespell/dictionary.txt";
 
 sub help {
        my ($exitcode) = @_;
@@ -88,6 +90,9 @@ Options:
                              file.  It's your fault if there's no backup or git
   --ignore-perl-version      override checking of perl version.  expect
                              runtime errors.
+  --codespell                Use the codespell dictionary for spelling/typos
+                             (default:/usr/local/share/codespell/dictionary.txt)
+  --codespellfile            Use this codespell dictionary
   -h, --help, --version      display this help and exit
 
 When FILE is - read standard input.
@@ -146,6 +151,8 @@ GetOptions(
        'ignore-perl-version!' => \$ignore_perl_version,
        'debug=s'       => \%debug,
        'test-only=s'   => \$tst_only,
+       'codespell!'    => \$codespell,
+       'codespellfile=s'       => \$codespellfile,
        'h|help'        => \$help,
        'version'       => \$help
 ) or help(1);
@@ -316,6 +323,7 @@ our $Operators      = qr{
 
 our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
 
+our $BasicType;
 our $NonptrType;
 our $NonptrTypeMisordered;
 our $NonptrTypeWithAttr;
@@ -436,6 +444,14 @@ foreach my $entry (@mode_permission_funcs) {
        $mode_perms_search .= $entry->[0];
 }
 
+our $mode_perms_world_writable = qr{
+       S_IWUGO         |
+       S_IWOTH         |
+       S_IRWXUGO       |
+       S_IALLUGO       |
+       0[0-7][0-7][2367]
+}x;
+
 our $allowed_asm_includes = qr{(?x:
        irq|
        memory|
@@ -449,7 +465,6 @@ my $misspellings;
 my %spelling_fix;
 
 if (open(my $spelling, '<', $spelling_file)) {
-       my @spelling_list;
        while (<$spelling>) {
                my $line = $_;
 
@@ -461,21 +476,50 @@ if (open(my $spelling, '<', $spelling_file)) {
 
                my ($suspect, $fix) = split(/\|\|/, $line);
 
-               push(@spelling_list, $suspect);
                $spelling_fix{$suspect} = $fix;
        }
        close($spelling);
-       $misspellings = join("|", @spelling_list);
 } else {
        warn "No typos will be found - file '$spelling_file': $!\n";
 }
 
+if ($codespell) {
+       if (open(my $spelling, '<', $codespellfile)) {
+               while (<$spelling>) {
+                       my $line = $_;
+
+                       $line =~ s/\s*\n?$//g;
+                       $line =~ s/^\s*//g;
+
+                       next if ($line =~ m/^\s*#/);
+                       next if ($line =~ m/^\s*$/);
+                       next if ($line =~ m/, disabled/i);
+
+                       $line =~ s/,.*$//;
+
+                       my ($suspect, $fix) = split(/->/, $line);
+
+                       $spelling_fix{$suspect} = $fix;
+               }
+               close($spelling);
+       } else {
+               warn "No codespell typos will be found - file '$codespellfile': $!\n";
+       }
+}
+
+$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
+
 sub build_types {
        my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
        my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
        my $Misordered = "(?x:  \n" . join("|\n  ", @typeListMisordered) . "\n)";
        my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
        $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
+       $BasicType      = qr{
+                               (?:$typeOtherOSTypedefs\b)|
+                               (?:$typeTypedefs\b)|
+                               (?:${all}\b)
+               }x;
        $NonptrType     = qr{
                        (?:$Modifier\s+|const\s+)*
                        (?:
@@ -1646,7 +1690,7 @@ sub fix_inserted_deleted_lines {
        foreach my $old_line (@{$linesRef}) {
                my $save_line = 1;
                my $line = $old_line;   #don't modify the array
-               if ($line =~ /^(?:\+\+\+\|\-\-\-)\s+\S+/) {     #new filename
+               if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) {      #new filename
                        $delta_offset = 0;
                } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) {    #new hunk
                        $range_last_linenr = $new_linenr;
@@ -1854,6 +1898,7 @@ sub process {
 
        my $in_header_lines = $file ? 0 : 1;
        my $in_commit_log = 0;          #Scanning lines before patch
+       my $commit_log_long_line = 0;
        my $reported_maintainer_file = 0;
        my $non_utf8_charset = 0;
 
@@ -2189,6 +2234,14 @@ sub process {
                              "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
                }
 
+# Check for line lengths > 75 in commit log, warn once
+               if ($in_commit_log && !$commit_log_long_line &&
+                   length($line) > 75) {
+                       WARN("COMMIT_LOG_LONG_LINE",
+                            "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
+                       $commit_log_long_line = 1;
+               }
+
 # Check for git id commit length and improperly formed commit descriptions
                if ($in_commit_log && $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i) {
                        my $init_char = $1;
@@ -2303,8 +2356,9 @@ sub process {
                }
 
 # Check for various typo / spelling mistakes
-               if (defined($misspellings) && ($in_commit_log || $line =~ /^\+/)) {
-                       while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:$|[^a-z@])/gi) {
+               if (defined($misspellings) &&
+                   ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
+                       while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
                                my $typo = $1;
                                my $typo_fix = $spelling_fix{lc($typo)};
                                $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
@@ -2459,8 +2513,9 @@ sub process {
 #line length limit
                if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
                    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
-                   !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ ||
-                   $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
+                   !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?$String\s*(?:|,|\)\s*;)\s*$/ ||
+                     $line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
+                     $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) &&
                    $length > $max_line_length)
                {
                        WARN("LONG_LINE",
@@ -2552,8 +2607,15 @@ sub process {
                        }
                }
 
-               if ($line =~ /^\+.*(\w+\s*)?\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|[,;:\?\(\{\}\[\<\>]|&&|\|\||\\$)/ &&
-                   (!defined($1) || $1 !~ /sizeof\s*/)) {
+# check for space after cast like "(int) foo" or "(struct foo) bar"
+# avoid checking a few false positives:
+#   "sizeof(<type>)" or "__alignof__(<type>)"
+#   function pointer declarations like "(*foo)(int) = bar;"
+#   structure definitions like "(struct foo) { 0 };"
+#   multiline macros that define functions
+#   known attributes or the __attribute__ keyword
+               if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ &&
+                   (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) {
                        if (CHK("SPACING",
                                "No space is necessary after a cast\n" . $herecurr) &&
                            $fix) {
@@ -3146,6 +3208,18 @@ sub process {
                                $herecurr);
                }
 
+# check for const <foo> const where <foo> is not a pointer or array type
+               if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
+                       my $found = $1;
+                       if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) {
+                               WARN("CONST_CONST",
+                                    "'const $found const *' should probably be 'const $found * const'\n" . $herecurr);
+                       } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) {
+                               WARN("CONST_CONST",
+                                    "'const $found const' should probably be 'const $found'\n" . $herecurr);
+                       }
+               }
+
 # check for non-global char *foo[] = {"bar", ...} declarations.
                if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
                        WARN("STATIC_CONST_CHAR_ARRAY",
@@ -3153,6 +3227,19 @@ sub process {
                                $herecurr);
                }
 
+# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
+               if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
+                       my $array = $1;
+                       if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
+                               my $array_div = $1;
+                               if (WARN("ARRAY_SIZE",
+                                        "Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
+                               }
+                       }
+               }
+
 # check for function declarations without arguments like "int foo()"
                if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
                        if (ERROR("FUNCTION_WITHOUT_ARGS",
@@ -3309,6 +3396,14 @@ sub process {
                             "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr);
                }
 
+# ENOSYS means "bad syscall nr" and nothing else.  This will have a small
+# number of false positives, but assembly files are not checked, so at
+# least the arch entry code will not trigger this warning.
+               if ($line =~ /\bENOSYS\b/) {
+                       WARN("ENOSYS",
+                            "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
+               }
+
 # function brace can't be on same line, except for #defines of do while,
 # or if closed on same line
                if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
@@ -3565,7 +3660,7 @@ sub process {
 
                                # Ignore operators passed as parameters.
                                if ($op_type ne 'V' &&
-                                   $ca =~ /\s$/ && $cc =~ /^\s*,/) {
+                                   $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) {
 
 #                              # Ignore comments
 #                              } elsif ($op =~ /^$;+$/) {
@@ -3750,6 +3845,14 @@ sub process {
                                                $ok = 1;
                                        }
 
+                                       # for asm volatile statements
+                                       # ignore a colon with another
+                                       # colon immediately before or after
+                                       if (($op eq ':') &&
+                                           ($ca =~ /:$/ || $cc =~ /^:/)) {
+                                               $ok = 1;
+                                       }
+
                                        # messages are ERROR, but ?: are CHK
                                        if ($ok == 0) {
                                                my $msg_type = \&ERROR;
@@ -3963,12 +4066,12 @@ sub process {
                        }
                }
 
-# Return of what appears to be an errno should normally be -'ve
-               if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+# Return of what appears to be an errno should normally be negative
+               if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
                        my $name = $1;
                        if ($name ne 'EOF' && $name ne 'ERROR') {
                                WARN("USE_NEGATIVE_ERRNO",
-                                    "return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+                                    "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
                        }
                }
 
@@ -4178,7 +4281,8 @@ sub process {
                        }
                }
 
-#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
+# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
+# itself <asm/foo.h> (uses RAW line)
                if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
                        my $file = "$1.h";
                        my $checkfile = "include/linux/$file";
@@ -4186,12 +4290,15 @@ sub process {
                            $realfile ne $checkfile &&
                            $1 !~ /$allowed_asm_includes/)
                        {
-                               if ($realfile =~ m{^arch/}) {
-                                       CHK("ARCH_INCLUDE_LINUX",
-                                           "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
-                               } else {
-                                       WARN("INCLUDE_LINUX",
-                                            "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+                               my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
+                               if ($asminclude > 0) {
+                                       if ($realfile =~ m{^arch/}) {
+                                               CHK("ARCH_INCLUDE_LINUX",
+                                                   "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+                                       } else {
+                                               WARN("INCLUDE_LINUX",
+                                                    "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+                                       }
                                }
                        }
                }
@@ -4700,6 +4807,16 @@ sub process {
                        }
                }
 
+# check for __read_mostly with const non-pointer (should just be const)
+               if ($line =~ /\b__read_mostly\b/ &&
+                   $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) {
+                       if (ERROR("CONST_READ_MOSTLY",
+                                 "Invalid use of __read_mostly with const type\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//;
+                       }
+               }
+
 # don't use __constant_<foo> functions outside of include/uapi/
                if ($realfile !~ m@^include/uapi/@ &&
                    $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
@@ -5261,6 +5378,7 @@ sub process {
                                stacktrace_ops|
                                sysfs_ops|
                                tty_operations|
+                               uart_ops|
                                usb_mon_operations|
                                wd_ops}x;
                if ($line !~ /\bconst\b/ &&
@@ -5318,8 +5436,8 @@ sub process {
                        }
                }
 
-               if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
-                   $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
+               if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
+                   $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
                        WARN("EXPORTED_WORLD_WRITABLE",
                             "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
                }
index fc7fd52..bb8e4d0 100644 (file)
@@ -825,6 +825,7 @@ retreived||retrieved
 retreive||retrieve
 retrive||retrieve
 retuned||returned
+reudce||reduce
 reuest||request
 reuqest||request
 reutnred||returned
index 2952ba5..b974a69 100644 (file)
@@ -948,15 +948,18 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
  */
 const char *tomoyo_get_exe(void)
 {
+       struct file *exe_file;
+       const char *cp;
        struct mm_struct *mm = current->mm;
-       const char *cp = NULL;
 
        if (!mm)
                return NULL;
-       down_read(&mm->mmap_sem);
-       if (mm->exe_file)
-               cp = tomoyo_realpath_from_path(&mm->exe_file->f_path);
-       up_read(&mm->mmap_sem);
+       exe_file = get_mm_exe_file(mm);
+       if (!exe_file)
+               return NULL;
+
+       cp = tomoyo_realpath_from_path(&exe_file->f_path);
+       fput(exe_file);
        return cp;
 }
 
index 5a30fdd..e12764d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/clk.h>
+#include <linux/kernel.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
@@ -31,8 +32,6 @@
 
 #define DIV_ROUND_DOWN_ULL(ll, d) \
        ({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
-#define DIV_ROUND_CLOSEST_ULL(ll, d) \
-       ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
 
 #define PCM512x_NUM_SUPPLIES 3
 static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {