Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Nov 2013 06:45:43 +0000 (15:45 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Nov 2013 06:45:43 +0000 (15:45 +0900)
Merge first patch-bomb from Andrew Morton:
 "Quite a lot of other stuff is banked up awaiting further
  next->mainline merging, but this batch contains:

   - Lots of random misc patches
   - OCFS2
   - Most of MM
   - backlight updates
   - lib/ updates
   - printk updates
   - checkpatch updates
   - epoll tweaking
   - rtc updates
   - hfs
   - hfsplus
   - documentation
   - procfs
   - update gcov to gcc-4.7 format
   - IPC"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (269 commits)
  ipc, msg: fix message length check for negative values
  ipc/util.c: remove unnecessary work pending test
  devpts: plug the memory leak in kill_sb
  ./Makefile: export initial ramdisk compression config option
  init/Kconfig: add option to disable kernel compression
  drivers: w1: make w1_slave::flags long to avoid memory corruption
  drivers/w1/masters/ds1wm.cuse dev_get_platdata()
  drivers/memstick/core/ms_block.c: fix unreachable state in h_msb_read_page()
  drivers/memstick/core/mspro_block.c: fix attributes array allocation
  drivers/pps/clients/pps-gpio.c: remove redundant of_match_ptr
  kernel/panic.c: reduce 1 byte usage for print tainted buffer
  gcov: reuse kbasename helper
  kernel/gcov/fs.c: use pr_warn()
  kernel/module.c: use pr_foo()
  gcov: compile specific gcov implementation based on gcc version
  gcov: add support for gcc 4.7 gcov format
  gcov: move gcov structs definitions to a gcc version specific file
  kernel/taskstats.c: return -ENOMEM when alloc memory fails in add_del_listener()
  kernel/taskstats.c: add nla_nest_cancel() for failure processing between nla_nest_start() and nla_nest_end()
  kernel/sysctl_binary.c: use scnprintf() instead of snprintf()
  ...

287 files changed:
CREDITS
Documentation/ABI/README
Documentation/backlight/lp855x-driver.txt
Documentation/cgroups/memory.txt
Documentation/cpu-hotplug.txt
Documentation/devicetree/bindings/video/backlight/lp855x.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/vfat.txt
Documentation/gcov.txt
Documentation/kernel-parameters.txt
Documentation/sysctl/kernel.txt
Documentation/sysctl/vm.txt
Documentation/trace/tracepoints.txt
Documentation/vm/zswap.txt
MAINTAINERS
Makefile
arch/alpha/include/uapi/asm/errno.h
arch/arm/kernel/module.c
arch/arm/mach-davinci/sram.c
arch/arm64/kernel/module.c
arch/cris/include/asm/io.h
arch/ia64/include/asm/processor.h
arch/ia64/mm/init.c
arch/metag/kernel/dma.c
arch/metag/mm/init.c
arch/microblaze/mm/consistent.c
arch/mips/include/uapi/asm/errno.h
arch/parisc/include/uapi/asm/errno.h
arch/parisc/kernel/module.c
arch/powerpc/mm/dma-noncoherent.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/numa.c
arch/s390/kernel/module.c
arch/s390/mm/mmap.c
arch/sh/include/asm/fpu.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/sh/kernel/cpu/fpu.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/mm/init.c
arch/sparc/include/uapi/asm/errno.h
arch/sparc/kernel/module.c
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/processor.h
arch/x86/kernel/i387.c
arch/x86/kernel/module.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/traps.c
arch/x86/mm/init.c
arch/x86/mm/numa.c
drivers/char/Kconfig
drivers/char/hpet.c
drivers/dma/mmp_tdma.c
drivers/iommu/omap-iopgtable.h
drivers/media/platform/coda.c
drivers/memstick/core/ms_block.c
drivers/memstick/core/mspro_block.c
drivers/message/i2o/driver.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/pps/clients/pps-gpio.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-88pm80x.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-as3722.c [new file with mode: 0644]
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-da9055.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds2404.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6900.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pl030.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-puv3.c
drivers/rtc/rtc-rs5c348.c
drivers/rtc/rtc-s5m.c [new file with mode: 0644]
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-sirfsoc.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-tps65910.c
drivers/rtc/rtc-v3020.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-vt8500.c
drivers/staging/lustre/lustre/include/lustre/lustre_errno.h
drivers/uio/uio_pruss.c
drivers/video/acornfb.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/aat2870_bl.c
drivers/video/backlight/adp5520_bl.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/adp8870_bl.c
drivers/video/backlight/ams369fg06.c
drivers/video/backlight/as3711_bl.c
drivers/video/backlight/atmel-pwm-bl.c
drivers/video/backlight/bd6107.c
drivers/video/backlight/corgi_lcd.c
drivers/video/backlight/cr_bllcd.c
drivers/video/backlight/da903x_bl.c
drivers/video/backlight/da9052_bl.c
drivers/video/backlight/ep93xx_bl.c
drivers/video/backlight/generic_bl.c
drivers/video/backlight/gpio_backlight.c
drivers/video/backlight/hx8357.c
drivers/video/backlight/ili922x.c
drivers/video/backlight/ili9320.c
drivers/video/backlight/kb3886_bl.c
drivers/video/backlight/l4f00242t03.c
drivers/video/backlight/ld9040.c
drivers/video/backlight/ld9040_gamma.h
drivers/video/backlight/lm3533_bl.c
drivers/video/backlight/lm3630_bl.c [deleted file]
drivers/video/backlight/lm3630a_bl.c [new file with mode: 0644]
drivers/video/backlight/lm3639_bl.c
drivers/video/backlight/lms283gf05.c
drivers/video/backlight/lms501kf03.c
drivers/video/backlight/lp855x_bl.c
drivers/video/backlight/lp8788_bl.c
drivers/video/backlight/ltv350qv.c
drivers/video/backlight/lv5207lp.c
drivers/video/backlight/max8925_bl.c
drivers/video/backlight/omap1_bl.c
drivers/video/backlight/pandora_bl.c
drivers/video/backlight/pcf50633-backlight.c
drivers/video/backlight/platform_lcd.c
drivers/video/backlight/pwm_bl.c
drivers/video/backlight/s6e63m0.c
drivers/video/backlight/tdo24m.c
drivers/video/backlight/tosa_bl.c
drivers/video/backlight/tps65217_bl.c
drivers/video/backlight/wm831x_bl.c
drivers/w1/masters/ds1wm.c
drivers/w1/w1.c
drivers/w1/w1.h
fs/cramfs/Kconfig
fs/debugfs/inode.c
fs/devpts/inode.c
fs/eventpoll.c
fs/exec.c
fs/fs-writeback.c
fs/hfs/btree.h
fs/hfsplus/btree.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/hfsplus_raw.h
fs/hfsplus/super.c
fs/hfsplus/xattr.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/buffer_head_io.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/file.c
fs/ocfs2/journal.h
fs/ocfs2/move_extents.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/resize.c
fs/ocfs2/stackglue.c
fs/ocfs2/suballoc.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/proc/Kconfig
fs/proc/inode.c
fs/proc/kcore.c
fs/proc/meminfo.c
fs/proc/task_mmu.c
fs/sync.c
fs/xfs/xfs_super.c
include/asm-generic/bitops/find.h
include/linux/binfmts.h
include/linux/compat.h
include/linux/genalloc.h
include/linux/init.h
include/linux/jump_label.h
include/linux/kernel-page-flags.h
include/linux/list.h
include/linux/memblock.h
include/linux/memory_hotplug.h
include/linux/mempolicy.h
include/linux/mfd/samsung/core.h
include/linux/mfd/samsung/rtc.h
include/linux/mm.h
include/linux/mman.h
include/linux/msg.h
include/linux/oom.h
include/linux/platform_data/lm3630_bl.h [deleted file]
include/linux/platform_data/lm3630a_bl.h [new file with mode: 0644]
include/linux/platform_data/lp855x.h
include/linux/rbtree.h
include/linux/sched.h
include/linux/syscalls.h
include/linux/vm_event_item.h
include/linux/writeback.h
include/trace/events/kmem.h
include/trace/events/writeback.h
include/uapi/asm-generic/errno.h
init/Kconfig
init/do_mounts.c
init/do_mounts_rd.c
init/main.c
ipc/msgutil.c
ipc/util.c
ipc/util.h
kernel/cpu.c
kernel/delayacct.c
kernel/events/core.c
kernel/gcov/Kconfig
kernel/gcov/Makefile
kernel/gcov/base.c
kernel/gcov/fs.c
kernel/gcov/gcc_3_4.c
kernel/gcov/gcc_4_7.c [new file with mode: 0644]
kernel/gcov/gcov.h
kernel/kprobes.c
kernel/kthread.c
kernel/module.c
kernel/panic.c
kernel/printk/printk.c
kernel/ptrace.c
kernel/sys.c
kernel/sysctl.c
kernel/sysctl_binary.c
kernel/taskstats.c
lib/Kconfig.debug
lib/Makefile
lib/debugobjects.c
lib/digsig.c
lib/genalloc.c
lib/percpu_test.c [new file with mode: 0644]
lib/show_mem.c
lib/vsprintf.c
mm/Kconfig
mm/bootmem.c
mm/compaction.c
mm/huge_memory.c
mm/kmemleak.c
mm/ksm.c
mm/memblock.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mmap.c
mm/mprotect.c
mm/nobootmem.c
mm/nommu.c
mm/page_alloc.c
mm/readahead.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/sparse.c
mm/swapfile.c
mm/util.c
mm/vmalloc.c
mm/vmstat.c
mm/zswap.c
scripts/checkpatch.pl
scripts/docproc.c
scripts/gen_initramfs_list.sh
scripts/kernel-doc
scripts/mod/modpost.c
scripts/sortextable.c
scripts/sortextable.h
sound/soc/davinci/davinci-pcm.c
sound/soc/pxa/mmp-pcm.c
tools/vm/page-types.c
usr/Makefile
usr/gen_init_cpio.c

diff --git a/CREDITS b/CREDITS
index b928516eea9038494f6b29bc37b990beb63a7780..4fc997d58ab2640a4b94fdcb1f363935f8a13395 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2576,7 +2576,7 @@ S: Toronto, Ontario
 S: Canada
 
 N: Zwane Mwaikambo
-E: zwane@arm.linux.org.uk
+E: zwanem@gmail.com
 D: Various driver hacking
 D: Lowlevel x86 kernel hacking
 D: General debugging
@@ -2895,6 +2895,11 @@ S: Framewood Road
 S: Wexham SL3 6PJ
 S: United Kingdom
 
+N: Richard Purdie
+E: rpurdie@rpsys.net
+D: Backlight subsystem maintainer
+S: United Kingdom
+
 N: Daniel Quinlan
 E: quinlan@pathname.com
 W: http://www.pathname.com/~quinlan/
index 10069828568b4e6d6b698e99c3aaccfe16128e12..1fafc4b0753b4eedf0bc00351286ff864745ab07 100644 (file)
@@ -72,3 +72,16 @@ kernel tree without going through the obsolete state first.
 
 It's up to the developer to place their interfaces in the category they
 wish for it to start out in.
+
+
+Notable bits of non-ABI, which should not under any circumstances be considered
+stable:
+
+- Kconfig.  Userspace should not rely on the presence or absence of any
+  particular Kconfig symbol, in /proc/config.gz, in the copy of .config
+  commonly installed to /boot, or in any invocation of the kernel build
+  process.
+
+- Kernel-internal symbols.  Do not rely on the presence, absence, location, or
+  type of any kernel symbol, either in System.map files or the kernel binary
+  itself.  See Documentation/stable_api_nonsense.txt.
index 1c732f0c675804b8e914c7f41cd7a862b2fc043d..01bce243d3d7c975462295d0d377ce7e88a69d51 100644 (file)
@@ -4,7 +4,8 @@ Kernel driver lp855x
 Backlight driver for LP855x ICs
 
 Supported chips:
-       Texas Instruments LP8550, LP8551, LP8552, LP8553, LP8556 and LP8557
+       Texas Instruments LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and
+       LP8557
 
 Author: Milo(Woogyom) Kim <milo.kim@ti.com>
 
@@ -24,7 +25,7 @@ Value : pwm based or register based
 
 2) chip_id
 The lp855x chip id.
-Value : lp8550/lp8551/lp8552/lp8553/lp8556/lp8557
+Value : lp8550/lp8551/lp8552/lp8553/lp8555/lp8556/lp8557
 
 Platform data for lp855x
 ------------------------
index 8af4ad12182869c4f972eeb9a5029c35e383b19a..e2bc132608fd47c025fda39f7ee488598ad6f5fc 100644 (file)
@@ -573,15 +573,19 @@ an memcg since the pages are allowed to be allocated from any physical
 node.  One of the use cases is evaluating application performance by
 combining this information with the application's CPU allocation.
 
-We export "total", "file", "anon" and "unevictable" pages per-node for
-each memcg.  The ouput format of memory.numa_stat is:
+Each memcg's numa_stat file includes "total", "file", "anon" and "unevictable"
+per-node page counts including "hierarchical_<counter>" which sums up all
+hierarchical children's values in addition to the memcg's own value.
+
+The ouput format of memory.numa_stat is:
 
 total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
 file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
 anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
 unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...
 
-And we have total = file + anon + unevictable.
+The "total" count is sum of file + anon + unevictable.
 
 6. Hierarchy support
 
index 786dc82f98ce4833c0ec8b1ecbcf8ad2a8f29ddf..8cb9938cc47e8c0e3d0202786bd9c434f96cbd4d 100644 (file)
@@ -5,7 +5,7 @@
                        Rusty Russell <rusty@rustcorp.com.au>
                        Srivatsa Vaddagiri <vatsa@in.ibm.com>
                i386:
-                       Zwane Mwaikambo <zwane@arm.linux.org.uk>
+                       Zwane Mwaikambo <zwanem@gmail.com>
                ppc64:
                        Nathan Lynch <nathanl@austin.ibm.com>
                        Joel Schopp <jschopp@austin.ibm.com>
index 1482103d288f8d4d4f2449eee4b5dfc159e364cf..96e83a56048e11aec37dd901179ba3fa39e53408 100644 (file)
@@ -2,7 +2,7 @@ lp855x bindings
 
 Required properties:
   - compatible: "ti,lp8550", "ti,lp8551", "ti,lp8552", "ti,lp8553",
-                "ti,lp8556", "ti,lp8557"
+                "ti,lp8555", "ti,lp8556", "ti,lp8557"
   - reg: I2C slave address (u8)
   - dev-ctrl: Value of DEVICE CONTROL register (u8). It depends on the device.
 
@@ -15,6 +15,33 @@ Optional properties:
 
 Example:
 
+       /* LP8555 */
+       backlight@2c {
+               compatible = "ti,lp8555";
+               reg = <0x2c>;
+
+               dev-ctrl = /bits/ 8 <0x00>;
+               pwm-period = <10000>;
+
+               /* 4V OV, 4 output LED0 string enabled */
+               rom_14h {
+                       rom-addr = /bits/ 8 <0x14>;
+                       rom-val = /bits/ 8 <0xcf>;
+               };
+
+               /* Heavy smoothing, 24ms ramp time step */
+               rom_15h {
+                       rom-addr = /bits/ 8 <0x15>;
+                       rom-val = /bits/ 8 <0xc7>;
+               };
+
+               /* 4 output LED1 string enabled */
+               rom_19h {
+                       rom-addr = /bits/ 8 <0x19>;
+                       rom-val = /bits/ 8 <0x0f>;
+               };
+       };
+
        /* LP8556 */
        backlight@2c {
                compatible = "ti,lp8556";
index 823c95faebd260af62618a647868ca904fd0eeab..22d89aa37218dbd2a36ba2a1359a8dca9b7c259f 100644 (file)
@@ -460,6 +460,7 @@ manner. The codes are the following:
     nl  - non-linear mapping
     ar  - architecture specific flag
     dd  - do not include area into core dump
+    sd  - soft-dirty flag
     mm  - mixed map area
     hg  - huge page advise flag
     nh  - no-huge page advise flag
index aa1f459fa6cf98fee624c0c559dc9ad1f90fe063..4a93e98b290a085793c495c9635b97335c58da56 100644 (file)
@@ -307,7 +307,7 @@ the following:
 
                 <proceeding files...>
                 <slot #3, id = 0x43, characters = "h is long">
-                <slot #2, id = 0x02, characters = "xtension which">
+                <slot #2, id = 0x02, characters = "xtension whic">
                 <slot #1, id = 0x01, characters = "My Big File.E">
                 <directory entry, name = "MYBIGFIL.EXT">
 
index e7ca6478cd93d4e6422d1ae92455b347dbdf7ccb..7b727783db7ed4f87a7c68b44b52054c62f48e85 100644 (file)
@@ -50,6 +50,10 @@ Configure the kernel with:
         CONFIG_DEBUG_FS=y
         CONFIG_GCOV_KERNEL=y
 
+select the gcc's gcov format, default is autodetect based on gcc version:
+
+        CONFIG_GCOV_FORMAT_AUTODETECT=y
+
 and to get coverage data for the entire kernel:
 
         CONFIG_GCOV_PROFILE_ALL=y
index fd3ecedc084d7a52dc926a4931f9dd89a55c9ee3..9ca3e74a10e128b4103d00dc8d06c12e6127d4c8 100644 (file)
@@ -1070,6 +1070,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                VIA, nVidia)
                        verbose: show contents of HPET registers during setup
 
+       hpet_mmap=      [X86, HPET_MMAP] Allow userspace to mmap HPET
+                       registers.  Default set by CONFIG_HPET_MMAP_DEFAULT.
+
        hugepages=      [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
        hugepagesz=     [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
                        On x86-64 and powerpc, this option can be specified
@@ -1775,6 +1778,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        that the amount of memory usable for all allocations
                        is not too small.
 
+       movable_node    [KNL,X86] Boot-time switch to enable the effects
+                       of CONFIG_MOVABLE_NODE=y. See mm/Kconfig for details.
+
        MTD_Partition=  [MTD]
                        Format: <name>,<region-number>,<size>,<offset>
 
index 4273b2d71a278cf26d3d381192c1de8ac4d7a340..26b7ee491df8912d070b5b9d33252e78f606e2ab 100644 (file)
@@ -290,13 +290,24 @@ Default value is "/sbin/hotplug".
 kptr_restrict:
 
 This toggle indicates whether restrictions are placed on
-exposing kernel addresses via /proc and other interfaces.  When
-kptr_restrict is set to (0), there are no restrictions.  When
-kptr_restrict is set to (1), the default, kernel pointers
-printed using the %pK format specifier will be replaced with 0's
-unless the user has CAP_SYSLOG.  When kptr_restrict is set to
-(2), kernel pointers printed using %pK will be replaced with 0's
-regardless of privileges.
+exposing kernel addresses via /proc and other interfaces.
+
+When kptr_restrict is set to (0), the default, there are no restrictions.
+
+When kptr_restrict is set to (1), kernel pointers printed using the %pK
+format specifier will be replaced with 0's unless the user has CAP_SYSLOG
+and effective user and group ids are equal to the real ids. This is
+because %pK checks are done at read() time rather than open() time, so
+if permissions are elevated between the open() and the read() (e.g via
+a setuid binary) then %pK will not leak kernel pointers to unprivileged
+users. Note, this is a temporary solution only. The correct long-term
+solution is to do the permission checks at open() time. Consider removing
+world read permissions from files that use %pK, and using dmesg_restrict
+to protect against uses of %pK in dmesg(8) if leaking kernel pointer
+values to unprivileged users is a concern.
+
+When kptr_restrict is set to (2), kernel pointers printed using
+%pK will be replaced with 0's regardless of privileges.
 
 ==============================================================
 
index 79a797eb3e879ac2aac45e546c62bd504404e2eb..1fbd4eb7b64aff335bed40a3d9ebbde95a26bcc1 100644 (file)
@@ -119,8 +119,11 @@ other appears as 0 when read.
 
 dirty_background_ratio
 
-Contains, as a percentage of total system memory, the number of pages at which
-the background kernel flusher threads will start writing out dirty data.
+Contains, as a percentage of total available memory that contains free pages
+and reclaimable pages, the number of pages at which the background kernel
+flusher threads will start writing out dirty data.
+
+The total avaiable memory is not equal to total system memory.
 
 ==============================================================
 
@@ -151,9 +154,11 @@ interval will be written out next time a flusher thread wakes up.
 
 dirty_ratio
 
-Contains, as a percentage of total system memory, the number of pages at which
-a process which is generating disk writes will itself start writing out dirty
-data.
+Contains, as a percentage of total available memory that contains free pages
+and reclaimable pages, the number of pages at which a process which is
+generating disk writes will itself start writing out dirty data.
+
+The total avaiable memory is not equal to total system memory.
 
 ==============================================================
 
index ac4170dd0f24d9adb67c9b857739e06926d39d0b..6b018b53177aa7ee499b5adb0e95d52e2e92d9ee 100644 (file)
@@ -114,3 +114,8 @@ core kernel image or in modules.
 If the tracepoint has to be used in kernel modules, an
 EXPORT_TRACEPOINT_SYMBOL_GPL() or EXPORT_TRACEPOINT_SYMBOL() can be
 used to export the defined tracepoints.
+
+Note: The convenience macro TRACE_EVENT provides an alternative way to
+      define tracepoints. Check http://lwn.net/Articles/379903,
+      http://lwn.net/Articles/381064 and http://lwn.net/Articles/383362
+      for a series of articles with more details.
index 7e492d8aaeafa957d8b00340b1f01671d3c9e1be..00c3d31e7971bb19a2341a103198c6207889d342 100644 (file)
@@ -8,7 +8,7 @@ significant performance improvement if reads from the compressed cache are
 faster than reads from a swap device.
 
 NOTE: Zswap is a new feature as of v3.11 and interacts heavily with memory
-reclaim.  This interaction has not be fully explored on the large set of
+reclaim.  This interaction has not been fully explored on the large set of
 potential configurations and workloads that exist.  For this reason, zswap
 is a work in progress and should be considered experimental.
 
@@ -23,7 +23,7 @@ Some potential benefits:
 Â Â Â  drastically reducing life-shortening writes.
 
 Zswap evicts pages from compressed cache on an LRU basis to the backing swap
-device when the compressed pool reaches it size limit.  This requirement had
+device when the compressed pool reaches its size limit.  This requirement had
 been identified in prior community discussions.
 
 To enabled zswap, the "enabled" attribute must be set to 1 at boot time.  e.g.
@@ -37,7 +37,7 @@ the backing swap device in the case that the compressed pool is full.
 
 Zswap makes use of zbud for the managing the compressed memory pool.  Each
 allocation in zbud is not directly accessible by address.  Rather, a handle is
-return by the allocation routine and that handle must be mapped before being
+returned by the allocation routine and that handle must be mapped before being
 accessed.  The compressed memory pool grows on demand and shrinks as compressed
 pages are freed.  The pool is not preallocated.
 
@@ -56,7 +56,7 @@ in the swap_map goes to 0) the swap code calls the zswap invalidate function,
 via frontswap, to free the compressed entry.
 
 Zswap seeks to be simple in its policies.  Sysfs attributes allow for one user
-controlled policies:
+controlled policy:
 * max_pool_percent - The maximum percentage of memory that the compressed
     pool can occupy.
 
index 051e4dc5b70fe03d9d5a5827b00dd12b0927c1f0..5cfa91b1974a22cafbda96e263c2a65d2a75b146 100644 (file)
@@ -1661,7 +1661,6 @@ S:        Maintained
 F:     drivers/net/wireless/b43legacy/
 
 BACKLIGHT CLASS/SUBSYSTEM
-M:     Richard Purdie <rpurdie@rpsys.net>
 M:     Jingoo Han <jg1.han@samsung.com>
 S:     Maintained
 F:     drivers/video/backlight/
@@ -2373,7 +2372,7 @@ F:        kernel/cpuset.c
 
 CRAMFS FILESYSTEM
 W:     http://sourceforge.net/projects/cramfs/
-S:     Orphan
+S:     Orphan / Obsolete
 F:     Documentation/filesystems/cramfs.txt
 F:     fs/cramfs/
 
@@ -7320,7 +7319,7 @@ S:        Odd Fixes
 F:     drivers/media/usb/tlg2300/
 
 SC1200 WDT DRIVER
-M:     Zwane Mwaikambo <zwane@arm.linux.org.uk>
+M:     Zwane Mwaikambo <zwanem@gmail.com>
 S:     Maintained
 F:     drivers/watchdog/sc1200wdt.c
 
index 67077ad6edbb26cbe7ea9b54efbc7ad51105548a..606a66cdcdb88e6e1b7d214dc7f87921c59e025d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -720,6 +720,22 @@ mod_strip_cmd = true
 endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
+# Select initial ramdisk compression format, default is gzip(1).
+# This shall be used by the dracut(8) tool while creating an initramfs image.
+#
+INITRD_COMPRESS=gzip
+ifeq ($(CONFIG_RD_BZIP2), y)
+        INITRD_COMPRESS=bzip2
+else ifeq ($(CONFIG_RD_LZMA), y)
+        INITRD_COMPRESS=lzma
+else ifeq ($(CONFIG_RD_XZ), y)
+        INITRD_COMPRESS=xz
+else ifeq ($(CONFIG_RD_LZO), y)
+        INITRD_COMPRESS=lzo
+else ifeq ($(CONFIG_RD_LZ4), y)
+        INITRD_COMPRESS=lz4
+endif
+export INITRD_COMPRESS
 
 ifdef CONFIG_MODULE_SIG_ALL
 MODSECKEY = ./signing_key.priv
index e5f29ca281800feb9f73237e458da4441bb19de4..17f92aa76b2f82cf312b28d009fa97cd3cdde837 100644 (file)
@@ -43,7 +43,7 @@
 
 #define        EUSERS          68      /* Too many users */
 #define        EDQUOT          69      /* Quota exceeded */
-#define        ESTALE          70      /* Stale NFS file handle */
+#define        ESTALE          70      /* Stale file handle */
 #define        EREMOTE         71      /* Object is remote */
 
 #define        ENOLCK          77      /* No record locks available */
index 084dc8896986f321247fc590b9f348cb47872eff..c9dfff3b80082e60fa2244efd1a23216293356ec 100644 (file)
@@ -40,7 +40,7 @@
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
+                               GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 #endif
index f18928b073f55de40cfab4d96ea7dd85c606d778..8540dddf1fbd56c2b1894bd0d37098dafc85a366 100644 (file)
@@ -25,7 +25,6 @@ struct gen_pool *sram_get_gen_pool(void)
 
 void *sram_alloc(size_t len, dma_addr_t *dma)
 {
-       unsigned long vaddr;
        dma_addr_t dma_base = davinci_soc_info.sram_dma;
 
        if (dma)
@@ -33,13 +32,7 @@ void *sram_alloc(size_t len, dma_addr_t *dma)
        if (!sram_pool || (dma && !dma_base))
                return NULL;
 
-       vaddr = gen_pool_alloc(sram_pool, len);
-       if (!vaddr)
-               return NULL;
-
-       if (dma)
-               *dma = gen_pool_virt_to_phys(sram_pool, vaddr);
-       return (void *)vaddr;
+       return gen_pool_dma_alloc(sram_pool, len, dma);
 
 }
 EXPORT_SYMBOL(sram_alloc);
index 2c28a6cf93e610a9484442f662c5975a180b7790..e2ad0d87721f74590e1c92be20cf1cc8fc6c6e52 100644 (file)
@@ -29,7 +29,7 @@
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                                   GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
+                                   GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 
index 5d3047e5563be8e09a583ba77882014bd4d0f578..4353cf239a135208660ff427b90d564fd32137a7 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/page.h>   /* for __va, __pa */
 #include <arch/io.h>
+#include <asm-generic/iomap.h>
 #include <linux/kernel.h>
 
 struct cris_io_operations
index e0a899a1a8a665c140dba6255dbbde7528a16c79..5a84b3a5074158d8b0fe975d5def50689c8c735d 100644 (file)
@@ -319,7 +319,7 @@ struct thread_struct {
        regs->loadrs = 0;                                                                       \
        regs->r8 = get_dumpable(current->mm);   /* set "don't zap registers" flag */            \
        regs->r12 = new_sp - 16;        /* allocate 16 byte scratch area */                     \
-       if (unlikely(!get_dumpable(current->mm))) {                                                     \
+       if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) {    \
                /*                                                                              \
                 * Zap scratch regs to avoid leaking bits between processes with different      \
                 * uid/privileges.                                                              \
index b6f7f43424ec492187f558b163b525d2d4583395..88504abf570429886183d32d9b857a90adb5c148 100644 (file)
@@ -357,9 +357,7 @@ int vmemmap_find_next_valid_pfn(int node, int i)
 
        end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
        end_address = PAGE_ALIGN(end_address);
-
-       stop_address = (unsigned long) &vmem_map[
-               pgdat->node_start_pfn + pgdat->node_spanned_pages];
+       stop_address = (unsigned long) &vmem_map[pgdat_end_pfn(pgdat)];
 
        do {
                pgd_t *pgd;
index 8c00dedadc54a4431083afe316f8734c0e6b99ef..db589ad5dbc41e5bb1cb0bc52dfc4faefc9c1820 100644 (file)
@@ -305,9 +305,7 @@ void dma_free_coherent(struct device *dev, size_t size,
 
                        if (pfn_valid(pfn)) {
                                struct page *page = pfn_to_page(pfn);
-                               ClearPageReserved(page);
-
-                               __free_page(page);
+                               __free_reserved_page(page);
                                continue;
                        }
                }
index 249fff66add37fb0c939241f8072163145e632a0..3cd6288f65c22bd8c0aed5968d886363d0a9f6fb 100644 (file)
@@ -148,7 +148,7 @@ static void __init bootmem_init_one_node(unsigned int nid)
        if (!p->node_spanned_pages)
                return;
 
-       end_pfn = p->node_start_pfn + p->node_spanned_pages;
+       end_pfn = pgdat_end_pfn(p);
 #ifdef CONFIG_HIGHMEM
        if (end_pfn > max_low_pfn)
                end_pfn = max_low_pfn;
index 5226b09cbbb28bae26605e082f24cfee8e672f85..dbbf2246a260fcb3e6d90e78b65655416ccf7d45 100644 (file)
@@ -176,8 +176,7 @@ void consistent_free(size_t size, void *vaddr)
        page = virt_to_page(vaddr);
 
        do {
-               ClearPageReserved(page);
-               __free_page(page);
+               __free_reserved_page(page);
                page++;
        } while (size -= PAGE_SIZE);
 #else
@@ -194,9 +193,7 @@ void consistent_free(size_t size, void *vaddr)
                        pte_clear(&init_mm, (unsigned int)vaddr, ptep);
                        if (pfn_valid(pfn)) {
                                page = pfn_to_page(pfn);
-
-                               ClearPageReserved(page);
-                               __free_page(page);
+                               __free_reserved_page(page);
                        }
                }
                vaddr += PAGE_SIZE;
index 31575e2fd1bdfe7f0a4228ada72f49515631faf3..02d645d7aa9a0ed9a49e40dadd70542ffef95ffa 100644 (file)
 #define EWOULDBLOCK    EAGAIN  /* Operation would block */
 #define EALREADY       149     /* Operation already in progress */
 #define EINPROGRESS    150     /* Operation now in progress */
-#define ESTALE         151     /* Stale NFS file handle */
+#define ESTALE         151     /* Stale file handle */
 #define ECANCELED      158     /* AIO operation canceled */
 
 /*
index 135ad6047e51e0733347ef7a3cfda3dfe9b0a9f7..f3a8aa554841c17a01af0625372c9e1838970979 100644 (file)
@@ -37,7 +37,7 @@
 #define        EBADMSG         67      /* Not a data message */
 #define        EUSERS          68      /* Too many users */
 #define        EDQUOT          69      /* Quota exceeded */
-#define        ESTALE          70      /* Stale NFS file handle */
+#define        ESTALE          70      /* Stale file handle */
 #define        EREMOTE         71      /* Object is remote */
 #define        EOVERFLOW       72      /* Value too large for defined data type */
 
index 2a625fb063e1537bcdff9dd18cc10dde87ec535f..50dfafc3f2c103aa3567f2fb88aeb94865847517 100644 (file)
@@ -219,7 +219,7 @@ void *module_alloc(unsigned long size)
         * init_data correctly */
        return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
                                    GFP_KERNEL | __GFP_HIGHMEM,
-                                   PAGE_KERNEL_RWX, -1,
+                                   PAGE_KERNEL_RWX, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 
index 6747eece84afd97e4d101e422b83f4616df61a67..7b6c10750179d163ff98e091d8e5dac863f2a2a0 100644 (file)
@@ -287,9 +287,7 @@ void __dma_free_coherent(size_t size, void *vaddr)
                        pte_clear(&init_mm, addr, ptep);
                        if (pfn_valid(pfn)) {
                                struct page *page = pfn_to_page(pfn);
-
-                               ClearPageReserved(page);
-                               __free_page(page);
+                               __free_reserved_page(page);
                        }
                }
                addr += PAGE_SIZE;
index d67db4bd672dd4223065c9b5470ee368a9456d1d..90bb6d9409bfd77b84eb62cd5b2cb594238780b1 100644 (file)
@@ -633,8 +633,6 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
 
 /*
  * This function frees user-level page tables of a process.
- *
- * Must be called with pagetable lock held.
  */
 void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                            unsigned long addr, unsigned long end,
index 33d67844062cbd6b1923052144aeb7945e528b35..078d3e00a6168fe7d56f212c0822800ee77bc9f8 100644 (file)
@@ -938,8 +938,7 @@ static void __init mark_reserved_regions_for_nid(int nid)
                unsigned long start_pfn = physbase >> PAGE_SHIFT;
                unsigned long end_pfn = PFN_UP(physbase + size);
                struct node_active_region node_ar;
-               unsigned long node_end_pfn = node->node_start_pfn +
-                                            node->node_spanned_pages;
+               unsigned long node_end_pfn = pgdat_end_pfn(node);
 
                /*
                 * Check to make sure that this memblock.reserved area is
index 7845e15a17df230285044265759e60572895373b..b89b59158b9592317479422b14cfb8e7779fa722 100644 (file)
@@ -50,7 +50,7 @@ void *module_alloc(unsigned long size)
        if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                                   GFP_KERNEL, PAGE_KERNEL, -1,
+                                   GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 #endif
index 6bcb045d2bd2f8ab3b1234e13f00be719dc0441e..9b436c21195ec6b16465bb6e1964e2ad343b8321 100644 (file)
@@ -64,6 +64,11 @@ static unsigned long mmap_rnd(void)
        return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
 }
 
+static unsigned long mmap_base_legacy(void)
+{
+       return TASK_UNMAPPED_BASE + mmap_rnd();
+}
+
 static inline unsigned long mmap_base(void)
 {
        unsigned long gap = rlimit(RLIMIT_STACK);
@@ -89,7 +94,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
         * bit is set, or if the expected stack growth is unlimited:
         */
        if (mmap_is_legacy()) {
-               mm->mmap_base = TASK_UNMAPPED_BASE;
+               mm->mmap_base = mmap_base_legacy();
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
                mm->mmap_base = mmap_base();
@@ -164,7 +169,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
         * bit is set, or if the expected stack growth is unlimited:
         */
        if (mmap_is_legacy()) {
-               mm->mmap_base = TASK_UNMAPPED_BASE;
+               mm->mmap_base = mmap_base_legacy();
                mm->get_unmapped_area = s390_get_unmapped_area;
        } else {
                mm->mmap_base = mmap_base();
index 06c4281aab65604af414c5081dde2b9871a3f952..09fc2bc8a790af4b7d74a31325d52985851cddec 100644 (file)
@@ -46,7 +46,7 @@ static inline void __unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs)
                save_fpu(tsk);
                release_fpu(regs);
        } else
-               tsk->fpu_counter = 0;
+               tsk->thread.fpu_counter = 0;
 }
 
 static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs)
index e699a12cdcca0da391ee072797c74208fa93eddb..18e0377f72bbb9ad8f559b00fc2452532d0ad312 100644 (file)
@@ -111,6 +111,16 @@ struct thread_struct {
 
        /* Extended processor state */
        union thread_xstate *xstate;
+
+       /*
+        * fpu_counter contains the number of consecutive context switches
+        * that the FPU is used. If this is over a threshold, the lazy fpu
+        * saving becomes unlazy to save the trap. This is an unsigned char
+        * so that after 256 times the counter wraps and the behavior turns
+        * lazy again; this to deal with bursty apps that only use FPU for
+        * a short time
+        */
+       unsigned char fpu_counter;
 };
 
 #define INIT_THREAD  {                                         \
index 1cc7d31971435ee57f9997539fcec28e061b6187..eedd4f625d07650e1f392a37b45e22d765e51602 100644 (file)
@@ -126,6 +126,16 @@ struct thread_struct {
 
        /* floating point info */
        union thread_xstate *xstate;
+
+       /*
+        * fpu_counter contains the number of consecutive context switches
+        * that the FPU is used. If this is over a threshold, the lazy fpu
+        * saving becomes unlazy to save the trap. This is an unsigned char
+        * so that after 256 times the counter wraps and the behavior turns
+        * lazy again; this to deal with bursty apps that only use FPU for
+        * a short time
+        */
+       unsigned char fpu_counter;
 };
 
 #define INIT_MMAP \
index f8f7af51c12892e6fc513a5a38aa8786789c163b..4e332244ea75c36b93fc63dfb9b1601e7f960759 100644 (file)
@@ -44,7 +44,7 @@ void __fpu_state_restore(void)
        restore_fpu(tsk);
 
        task_thread_info(tsk)->status |= TS_USEDFPU;
-       tsk->fpu_counter++;
+       tsk->thread.fpu_counter++;
 }
 
 void fpu_state_restore(struct pt_regs *regs)
index ebd3933005b46b0cb773e7274c459290889bfc87..2885fc9d9dcdc9b9deec12c9a8a0ac681b366f1f 100644 (file)
@@ -156,7 +156,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 #endif
                ti->addr_limit = KERNEL_DS;
                ti->status &= ~TS_USEDFPU;
-               p->fpu_counter = 0;
+               p->thread.fpu_counter = 0;
                return 0;
        }
        *childregs = *current_pt_regs();
@@ -189,7 +189,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
        unlazy_fpu(prev, task_pt_regs(prev));
 
        /* we're going to use this soon, after a few expensive things */
-       if (next->fpu_counter > 5)
+       if (next->thread.fpu_counter > 5)
                prefetch(next_t->xstate);
 
 #ifdef CONFIG_MMU
@@ -207,7 +207,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
         * restore of the math state immediately to avoid the trap; the
         * chances of needing FPU soon are obviously high now
         */
-       if (next->fpu_counter > 5)
+       if (next->thread.fpu_counter > 5)
                __fpu_state_restore();
 
        return prev;
index 174d124b419e792f936773ef8e29373154f01cba..e2062e643341ccbb744ec9cb9f446bb36850ec8c 100644 (file)
@@ -374,7 +374,7 @@ asmlinkage void ret_from_kernel_thread(void);
 int copy_thread(unsigned long clone_flags, unsigned long usp,
                unsigned long arg, struct task_struct *p)
 {
-       struct pt_regs *childregs, *regs = current_pt_regs();
+       struct pt_regs *childregs;
 
 #ifdef CONFIG_SH_FPU
        /* can't happen for a kernel thread */
@@ -393,7 +393,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        if (unlikely(p->flags & PF_KTHREAD)) {
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->regs[2] = (unsigned long)arg;
-               childregs->regs[3] = (unsigned long)fn;
+               childregs->regs[3] = (unsigned long)usp;
                childregs->sr = (1 << 30); /* not user_mode */
                childregs->sr |= SR_FD; /* Invalidate FPU flag */
                p->thread.pc = (unsigned long) ret_from_kernel_thread;
index 33890fd267cb056c979def415ff6d49f054c55c4..2d089fe2cba910153e8d9bf1db927fd18ca9a83d 100644 (file)
@@ -231,7 +231,7 @@ static void __init bootmem_init_one_node(unsigned int nid)
        if (!p->node_spanned_pages)
                return;
 
-       end_pfn = p->node_start_pfn + p->node_spanned_pages;
+       end_pfn = pgdat_end_pfn(p);
 
        total_pages = bootmem_bootmap_pages(p->node_spanned_pages);
 
index c351aba997b7d377f4a1591e8abf0821b9540e51..20423e17285342d40c21796c9baafac5eb1f68b4 100644 (file)
@@ -40,7 +40,7 @@
 #define EPROCLIM        67      /* SUNOS: Too many processes */
 #define        EUSERS          68      /* Too many users */
 #define        EDQUOT          69      /* Quota exceeded */
-#define        ESTALE          70      /* Stale NFS file handle */
+#define        ESTALE          70      /* Stale file handle */
 #define        EREMOTE         71      /* Object is remote */
 #define        ENOSTR          72      /* Device not a stream */
 #define        ETIME           73      /* Timer expired */
index 4435488ebe258580afd7177dc61579e2c3727044..97655e0fd2438cdee8188bb4748a3c1c87f825fa 100644 (file)
@@ -29,7 +29,7 @@ static void *module_map(unsigned long size)
        if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL, -1,
+                               GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 #else
index 4d0bda7b11e3b6715b026f5995183ddb4e218ae1..c49a613c6452fc66afdf5de52572dc8d033a8fcc 100644 (file)
@@ -365,7 +365,7 @@ static inline void drop_fpu(struct task_struct *tsk)
         * Forget coprocessor state..
         */
        preempt_disable();
-       tsk->fpu_counter = 0;
+       tsk->thread.fpu_counter = 0;
        __drop_fpu(tsk);
        clear_used_math();
        preempt_enable();
@@ -424,7 +424,7 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
         * or if the past 5 consecutive context-switches used math.
         */
        fpu.preload = tsk_used_math(new) && (use_eager_fpu() ||
-                                            new->fpu_counter > 5);
+                                            new->thread.fpu_counter > 5);
        if (__thread_has_fpu(old)) {
                if (!__save_init_fpu(old))
                        cpu = ~0;
@@ -433,16 +433,16 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
 
                /* Don't change CR0.TS if we just switch! */
                if (fpu.preload) {
-                       new->fpu_counter++;
+                       new->thread.fpu_counter++;
                        __thread_set_has_fpu(new);
                        prefetch(new->thread.fpu.state);
                } else if (!use_eager_fpu())
                        stts();
        } else {
-               old->fpu_counter = 0;
+               old->thread.fpu_counter = 0;
                old->thread.fpu.last_cpu = ~0;
                if (fpu.preload) {
-                       new->fpu_counter++;
+                       new->thread.fpu_counter++;
                        if (!use_eager_fpu() && fpu_lazy_restore(new, cpu))
                                fpu.preload = 0;
                        else
index 987c75ecc334da595401237fe95bf2b3c743b749..7b034a4057f93c7cf01a5bc65204e723fff137e8 100644 (file)
@@ -488,6 +488,15 @@ struct thread_struct {
        unsigned long           iopl;
        /* Max allowed port in the bitmap, in bytes: */
        unsigned                io_bitmap_max;
+       /*
+        * fpu_counter contains the number of consecutive context switches
+        * that the FPU is used. If this is over a threshold, the lazy fpu
+        * saving becomes unlazy to save the trap. This is an unsigned char
+        * so that after 256 times the counter wraps and the behavior turns
+        * lazy again; this to deal with bursty apps that only use FPU for
+        * a short time
+        */
+       unsigned char fpu_counter;
 };
 
 /*
index 5d576ab344030832617450ac2330d63f135596a4..e8368c6dd2a2988c2d9d68cacc7030554424ad70 100644 (file)
@@ -100,7 +100,7 @@ void unlazy_fpu(struct task_struct *tsk)
                __save_init_fpu(tsk);
                __thread_fpu_end(tsk);
        } else
-               tsk->fpu_counter = 0;
+               tsk->thread.fpu_counter = 0;
        preempt_enable();
 }
 EXPORT_SYMBOL(unlazy_fpu);
index 216a4d754b0c7b2b01a822928ddb7a802a1bca8b..18be189368bbfdbf55cc2e7492c0e7b3b2514403 100644 (file)
@@ -49,7 +49,7 @@ void *module_alloc(unsigned long size)
                return NULL;
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
                                GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
-                               -1, __builtin_return_address(0));
+                               NUMA_NO_NODE, __builtin_return_address(0));
 }
 
 #ifdef CONFIG_X86_32
index c2ec1aa6d45467bddd5f4c09189e4160b4fb2476..6f1236c29c4b575ec429dcc34d23629321ca5c0a 100644 (file)
@@ -153,7 +153,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                childregs->orig_ax = -1;
                childregs->cs = __KERNEL_CS | get_kernel_rpl();
                childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
-               p->fpu_counter = 0;
+               p->thread.fpu_counter = 0;
                p->thread.io_bitmap_ptr = NULL;
                memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
                return 0;
@@ -166,7 +166,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        p->thread.ip = (unsigned long) ret_from_fork;
        task_user_gs(p) = get_user_gs(current_pt_regs());
 
-       p->fpu_counter = 0;
+       p->thread.fpu_counter = 0;
        p->thread.io_bitmap_ptr = NULL;
        tsk = current;
        err = -ENOMEM;
index 45ab4d6fc8a7af0409c56b0f8cd1170124b57858..10fe4c189621199361fedd0bfe15e41b71e3e15e 100644 (file)
@@ -163,7 +163,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        p->thread.sp = (unsigned long) childregs;
        p->thread.usersp = me->thread.usersp;
        set_tsk_thread_flag(p, TIF_FORK);
-       p->fpu_counter = 0;
+       p->thread.fpu_counter = 0;
        p->thread.io_bitmap_ptr = NULL;
 
        savesegment(gs, p->thread.gsindex);
index 918d489fa53df02dda1b4996190ef1a70f769078..cb233bc9dee35681ccf85a2385ece964ee96847d 100644 (file)
@@ -1121,8 +1121,6 @@ void __init setup_arch(char **cmdline_p)
        acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
 #endif
 
-       reserve_crashkernel();
-
        vsmp_init();
 
        io_delay_init();
@@ -1135,6 +1133,13 @@ void __init setup_arch(char **cmdline_p)
        early_acpi_boot_init();
 
        initmem_init();
+
+       /*
+        * Reserve memory for crash kernel after SRAT is parsed so that it
+        * won't consume hotpluggable memory.
+        */
+       reserve_crashkernel();
+
        memblock_find_dma_reserve();
 
 #ifdef CONFIG_KVM_GUEST
index 729aa779ff7523fda90b0031e9dab09316a5beae..996ce2313ce65826531180fecde2d542fbcf561b 100644 (file)
@@ -653,7 +653,7 @@ void math_state_restore(void)
                return;
        }
 
-       tsk->fpu_counter++;
+       tsk->thread.fpu_counter++;
 }
 EXPORT_SYMBOL_GPL(math_state_restore);
 
index ce32017c5e38dc1b3ba14f08c6a82a13113d73de..f9713061811332100ee6560ec736b0c18c509e45 100644 (file)
@@ -53,12 +53,12 @@ __ref void *alloc_low_pages(unsigned int num)
        if ((pgt_buf_end + num) > pgt_buf_top || !can_use_brk_pgt) {
                unsigned long ret;
                if (min_pfn_mapped >= max_pfn_mapped)
-                       panic("alloc_low_page: ran out of memory");
+                       panic("alloc_low_pages: ran out of memory");
                ret = memblock_find_in_range(min_pfn_mapped << PAGE_SHIFT,
                                        max_pfn_mapped << PAGE_SHIFT,
                                        PAGE_SIZE * num , PAGE_SIZE);
                if (!ret)
-                       panic("alloc_low_page: can not alloc memory");
+                       panic("alloc_low_pages: can not alloc memory");
                memblock_reserve(ret, PAGE_SIZE * num);
                pfn = ret >> PAGE_SHIFT;
        } else {
@@ -418,27 +418,27 @@ static unsigned long __init get_new_step_size(unsigned long step_size)
        return step_size << 5;
 }
 
-void __init init_mem_mapping(void)
+/**
+ * memory_map_top_down - Map [map_start, map_end) top down
+ * @map_start: start address of the target memory range
+ * @map_end: end address of the target memory range
+ *
+ * This function will setup direct mapping for memory range
+ * [map_start, map_end) in top-down. That said, the page tables
+ * will be allocated at the end of the memory, and we map the
+ * memory in top-down.
+ */
+static void __init memory_map_top_down(unsigned long map_start,
+                                      unsigned long map_end)
 {
-       unsigned long end, real_end, start, last_start;
+       unsigned long real_end, start, last_start;
        unsigned long step_size;
        unsigned long addr;
        unsigned long mapped_ram_size = 0;
        unsigned long new_mapped_ram_size;
 
-       probe_page_size_mask();
-
-#ifdef CONFIG_X86_64
-       end = max_pfn << PAGE_SHIFT;
-#else
-       end = max_low_pfn << PAGE_SHIFT;
-#endif
-
-       /* the ISA range is always mapped regardless of memory holes */
-       init_memory_mapping(0, ISA_END_ADDRESS);
-
        /* xen has big range in reserved near end of ram, skip it at first.*/
-       addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, PMD_SIZE);
+       addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE);
        real_end = addr + PMD_SIZE;
 
        /* step_size need to be small so pgt_buf from BRK could cover it */
@@ -453,13 +453,13 @@ void __init init_mem_mapping(void)
         * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages
         * for page table.
         */
-       while (last_start > ISA_END_ADDRESS) {
+       while (last_start > map_start) {
                if (last_start > step_size) {
                        start = round_down(last_start - 1, step_size);
-                       if (start < ISA_END_ADDRESS)
-                               start = ISA_END_ADDRESS;
+                       if (start < map_start)
+                               start = map_start;
                } else
-                       start = ISA_END_ADDRESS;
+                       start = map_start;
                new_mapped_ram_size = init_range_memory_mapping(start,
                                                        last_start);
                last_start = start;
@@ -470,8 +470,89 @@ void __init init_mem_mapping(void)
                mapped_ram_size += new_mapped_ram_size;
        }
 
-       if (real_end < end)
-               init_range_memory_mapping(real_end, end);
+       if (real_end < map_end)
+               init_range_memory_mapping(real_end, map_end);
+}
+
+/**
+ * memory_map_bottom_up - Map [map_start, map_end) bottom up
+ * @map_start: start address of the target memory range
+ * @map_end: end address of the target memory range
+ *
+ * This function will setup direct mapping for memory range
+ * [map_start, map_end) in bottom-up. Since we have limited the
+ * bottom-up allocation above the kernel, the page tables will
+ * be allocated just above the kernel and we map the memory
+ * in [map_start, map_end) in bottom-up.
+ */
+static void __init memory_map_bottom_up(unsigned long map_start,
+                                       unsigned long map_end)
+{
+       unsigned long next, new_mapped_ram_size, start;
+       unsigned long mapped_ram_size = 0;
+       /* step_size need to be small so pgt_buf from BRK could cover it */
+       unsigned long step_size = PMD_SIZE;
+
+       start = map_start;
+       min_pfn_mapped = start >> PAGE_SHIFT;
+
+       /*
+        * We start from the bottom (@map_start) and go to the top (@map_end).
+        * The memblock_find_in_range() gets us a block of RAM from the
+        * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages
+        * for page table.
+        */
+       while (start < map_end) {
+               if (map_end - start > step_size) {
+                       next = round_up(start + 1, step_size);
+                       if (next > map_end)
+                               next = map_end;
+               } else
+                       next = map_end;
+
+               new_mapped_ram_size = init_range_memory_mapping(start, next);
+               start = next;
+
+               if (new_mapped_ram_size > mapped_ram_size)
+                       step_size = get_new_step_size(step_size);
+               mapped_ram_size += new_mapped_ram_size;
+       }
+}
+
+void __init init_mem_mapping(void)
+{
+       unsigned long end;
+
+       probe_page_size_mask();
+
+#ifdef CONFIG_X86_64
+       end = max_pfn << PAGE_SHIFT;
+#else
+       end = max_low_pfn << PAGE_SHIFT;
+#endif
+
+       /* the ISA range is always mapped regardless of memory holes */
+       init_memory_mapping(0, ISA_END_ADDRESS);
+
+       /*
+        * If the allocation is in bottom-up direction, we setup direct mapping
+        * in bottom-up, otherwise we setup direct mapping in top-down.
+        */
+       if (memblock_bottom_up()) {
+               unsigned long kernel_end = __pa_symbol(_end);
+
+               /*
+                * we need two separate calls here. This is because we want to
+                * allocate page tables above the kernel. So we first map
+                * [kernel_end, end) to make memory above the kernel be mapped
+                * as soon as possible. And then use page tables allocated above
+                * the kernel to map [ISA_END_ADDRESS, kernel_end).
+                */
+               memory_map_bottom_up(kernel_end, end);
+               memory_map_bottom_up(ISA_END_ADDRESS, kernel_end);
+       } else {
+               memory_map_top_down(ISA_END_ADDRESS, end);
+       }
 
 #ifdef CONFIG_X86_64
        if (max_pfn > max_low_pfn) {
index 8bf93bae1f13f939e2ca88faccd244c2b39df780..24aec58d6afdf4ec75390f15413ed26cb47653e8 100644 (file)
@@ -567,6 +567,17 @@ static int __init numa_init(int (*init_func)(void))
        ret = init_func();
        if (ret < 0)
                return ret;
+
+       /*
+        * We reset memblock back to the top-down direction
+        * here because if we configured ACPI_NUMA, we have
+        * parsed SRAT in init_func(). It is ok to have the
+        * reset here even if we did't configure ACPI_NUMA
+        * or acpi numa init fails and fallbacks to dummy
+        * numa init.
+        */
+       memblock_set_bottom_up(false);
+
        ret = numa_cleanup_meminfo(&numa_meminfo);
        if (ret < 0)
                return ret;
index 14219972c745ae6f31636e6e6bd0e89335f22c08..fa3243d71c76d0b9f14dde9066a2bff60a18165c 100644 (file)
@@ -522,10 +522,16 @@ config HPET_MMAP
          If you say Y here, user applications will be able to mmap
          the HPET registers.
 
+config HPET_MMAP_DEFAULT
+       bool "Enable HPET MMAP access by default"
+       default y
+       depends on HPET_MMAP
+       help
          In some hardware implementations, the page containing HPET
          registers may also contain other things that shouldn't be
-         exposed to the user.  If this applies to your hardware,
-         say N here.
+         exposed to the user.  This option selects the default (if
+         kernel parameter hpet_mmap is not set) user access to the
+         registers for applications that require it.
 
 config HANGCHECK_TIMER
        tristate "Hangcheck timer"
index dca5834685cf93d0cd105e66a7cf656329fc3e2e..5d9c31dfc905eac973f167d4f77d1c8b628de0b0 100644 (file)
@@ -367,12 +367,29 @@ static unsigned int hpet_poll(struct file *file, poll_table * wait)
        return 0;
 }
 
+#ifdef CONFIG_HPET_MMAP
+#ifdef CONFIG_HPET_MMAP_DEFAULT
+static int hpet_mmap_enabled = 1;
+#else
+static int hpet_mmap_enabled = 0;
+#endif
+
+static __init int hpet_mmap_enable(char *str)
+{
+       get_option(&str, &hpet_mmap_enabled);
+       pr_info("HPET mmap %s\n", hpet_mmap_enabled ? "enabled" : "disabled");
+       return 1;
+}
+__setup("hpet_mmap", hpet_mmap_enable);
+
 static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 {
-#ifdef CONFIG_HPET_MMAP
        struct hpet_dev *devp;
        unsigned long addr;
 
+       if (!hpet_mmap_enabled)
+               return -EACCES;
+
        devp = file->private_data;
        addr = devp->hd_hpets->hp_hpet_phys;
 
@@ -381,10 +398,13 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
        return vm_iomap_memory(vma, addr, PAGE_SIZE);
+}
 #else
+static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
+{
        return -ENOSYS;
-#endif
 }
+#endif
 
 static int hpet_fasync(int fd, struct file *file, int on)
 {
index 38cb517fb2ebd82034b02e2ab7d5cabfc9992cbd..d3b6358e5a27037281f6da2efb6dad3e926b9fb1 100644 (file)
@@ -350,12 +350,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
        if (!gpool)
                return NULL;
 
-       tdmac->desc_arr = (void *)gen_pool_alloc(gpool, size);
-       if (!tdmac->desc_arr)
-               return NULL;
-
-       tdmac->desc_arr_phys = gen_pool_virt_to_phys(gpool,
-                       (unsigned long)tdmac->desc_arr);
+       tdmac->desc_arr = gen_pool_dma_alloc(gpool, size, &tdmac->desc_arr_phys);
 
        return tdmac->desc_arr;
 }
index f4003d568a923a89d7f766abd77718f03cf1e74a..b6f9a51746caad5956442e7d99a1b5450cf72f0b 100644 (file)
@@ -95,4 +95,4 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
 #define iopte_offset(iopgd, da)        (iopgd_page_vaddr(iopgd) + iopte_index(da))
 
 #define to_iommu(dev)                                                  \
-       ((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev)))
+       (platform_get_drvdata(to_platform_device(dev)))
index 449d2fec9e87454aa85f34a0642aa61919d376a5..4993610051eeeb586005712060732ef2539390b2 100644 (file)
@@ -3232,13 +3232,12 @@ static int coda_probe(struct platform_device *pdev)
                dev->iram_size = CODA7_IRAM_SIZE;
                break;
        }
-       dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size);
+       dev->iram_vaddr = (unsigned long)gen_pool_dma_alloc(dev->iram_pool,
+                       dev->iram_size, (dma_addr_t *)&dev->iram_paddr);
        if (!dev->iram_vaddr) {
                dev_err(&pdev->dev, "unable to alloc iram\n");
                return -ENOMEM;
        }
-       dev->iram_paddr = gen_pool_virt_to_phys(dev->iram_pool,
-                                               dev->iram_vaddr);
 
        platform_set_drvdata(pdev, dev);
 
index 08e70232062fbcdde628d33afef1a4f5f3f93de0..9188ef5d677ede05a5cb2c56d176bfb878321185 100644 (file)
@@ -401,7 +401,7 @@ again:
                        sizeof(struct ms_status_register)))
                        return 0;
 
-               msb->state = MSB_RP_RECEIVE_OOB_READ;
+               msb->state = MSB_RP_RECIVE_STATUS_REG;
                return 0;
 
        case MSB_RP_RECIVE_STATUS_REG:
index f4176ca3a794ee2c684d35e3461da165b1abc7ce..fc145d202c46907cf1ed40572068fcf3d21441c1 100644 (file)
@@ -1023,8 +1023,8 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
        } else
                attr_count = attr->count;
 
-       msb->attr_group.attrs = kzalloc((attr_count + 1)
-                                       * sizeof(struct attribute),
+       msb->attr_group.attrs = kcalloc(attr_count + 1,
+                                       sizeof(*msb->attr_group.attrs),
                                        GFP_KERNEL);
        if (!msb->attr_group.attrs) {
                rc = -ENOMEM;
index b6b92d760510be0f5cd92009a616fbccc9ce088d..1b18a0d1d05bdfd3a7ce364b221ee0a2ae59f5cd 100644 (file)
@@ -105,7 +105,8 @@ int i2o_driver_register(struct i2o_driver *drv)
                        osm_err("too many drivers registered, increase "
                                "max_drivers\n");
                        spin_unlock_irqrestore(&i2o_drivers_lock, flags);
-                       return -EFAULT;
+                       rc = -EFAULT;
+                       goto out;
                }
 
        drv->context = i;
@@ -124,11 +125,14 @@ int i2o_driver_register(struct i2o_driver *drv)
        }
 
        rc = driver_register(&drv->driver);
-       if (rc) {
-               if (drv->event) {
-                       destroy_workqueue(drv->event_queue);
-                       drv->event_queue = NULL;
-               }
+       if (rc)
+               goto out;
+
+       return 0;
+out:
+       if (drv->event_queue) {
+               destroy_workqueue(drv->event_queue);
+               drv->event_queue = NULL;
        }
 
        return rc;
index 9fbeee522d2cd9c0741de1141eda427eead6246b..32c92abf50949fa1494812ab9d3734a5a2f3db1f 100644 (file)
@@ -1217,9 +1217,6 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
                                     ETH_VLAN_FILTER_CLASSIFY, config);
 }
 
-#define list_next_entry(pos, member) \
-       list_entry((pos)->member.next, typeof(*(pos)), member)
-
 /**
  * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
  *
index 9966124ad988510e25200e3196474208a7a40fa9..f41bacfdc3dc39de70ff713b32f8b82b8cb7e6ff 100644 (file)
@@ -201,7 +201,7 @@ static struct platform_driver pps_gpio_driver = {
        .driver         = {
                .name   = PPS_GPIO_NAME,
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(pps_gpio_dt_ids),
+               .of_match_table = pps_gpio_dt_ids,
        },
 };
 
index 9654aa3c05cbd87c89b7c7ee2a8d8ebf34d5326e..15f166a470a7f3fe5eb0e45dd2be80c2a384a76d 100644 (file)
@@ -153,6 +153,16 @@ config RTC_DRV_88PM80X
          This driver can also be built as a module. If so, the module
          will be called rtc-88pm80x.
 
+config RTC_DRV_AS3722
+       tristate "ams AS3722 RTC driver"
+       depends on MFD_AS3722
+       help
+         If you say yes here you get support for the RTC of ams AS3722 PMIC
+         chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-as3722.
+
 config RTC_DRV_DS1307
        tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
        help
@@ -497,6 +507,16 @@ config RTC_DRV_RV3029C2
          This driver can also be built as a module. If so, the module
          will be called rtc-rv3029c2.
 
+config RTC_DRV_S5M
+       tristate "Samsung S5M series"
+       depends on MFD_SEC_CORE
+       help
+         If you say yes here you will get support for the
+         RTC of Samsung S5M PMIC series.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-s5m.
+
 endif # I2C
 
 comment "SPI RTC drivers"
index 2dff3d2009b5f5a3cad9e30b0eed0e726e9a51e1..27b4bd8840666003d9a1d27f8aa04306a39070b4 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-88pm860x.o
 obj-$(CONFIG_RTC_DRV_88PM80X)  += rtc-88pm80x.o
 obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
+obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
@@ -107,6 +108,7 @@ obj-$(CONFIG_RTC_DRV_RX8025)        += rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)   += rtc-rx8581.o
 obj-$(CONFIG_RTC_DRV_S35390A)  += rtc-s35390a.o
 obj-$(CONFIG_RTC_DRV_S3C)      += rtc-s3c.o
+obj-$(CONFIG_RTC_DRV_S5M)      += rtc-s5m.o
 obj-$(CONFIG_RTC_DRV_SA1100)   += rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
 obj-$(CONFIG_RTC_DRV_SNVS)     += rtc-snvs.o
index 354c937a58665a753ad3ee9b697741264476ec65..0916089c7c3e8f44db3d8f336f8932476c64b09b 100644 (file)
@@ -251,14 +251,15 @@ static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);
 static int pm80x_rtc_probe(struct platform_device *pdev)
 {
        struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm80x_platform_data *pm80x_pdata;
+       struct pm80x_platform_data *pm80x_pdata =
+                               dev_get_platdata(pdev->dev.parent);
        struct pm80x_rtc_pdata *pdata = NULL;
        struct pm80x_rtc_info *info;
        struct rtc_time tm;
        unsigned long ticks = 0;
        int ret;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (pdata == NULL)
                dev_warn(&pdev->dev, "No platform data!\n");
 
@@ -326,8 +327,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
        regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,
                           PM800_RTC1_USE_XO);
 
-       if (pdev->dev.parent->platform_data) {
-               pm80x_pdata = pdev->dev.parent->platform_data;
+       if (pm80x_pdata) {
                pdata = pm80x_pdata->rtc;
                if (pdata)
                        info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
index 4e30c85728e5078b7b635c5bc7be4c2eaa4b3476..816504846cdda92fa97aa4f2dcae5f98953443bf 100644 (file)
@@ -316,7 +316,7 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
        unsigned long ticks = 0;
        int ret;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 
        info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_rtc_info),
                            GFP_KERNEL);
diff --git a/drivers/rtc/rtc-as3722.c b/drivers/rtc/rtc-as3722.c
new file mode 100644 (file)
index 0000000..9cfa817
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * rtc-as3722.c - Real Time Clock driver for ams AS3722 PMICs
+ *
+ * Copyright (C) 2013 ams AG
+ * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.com>
+ * Author: Laxman Dewangan <ldewangan@nvidia.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bcd.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/time.h>
+
+#define AS3722_RTC_START_YEAR    2000
+struct as3722_rtc {
+       struct rtc_device       *rtc;
+       struct device           *dev;
+       struct as3722           *as3722;
+       int                     alarm_irq;
+       bool                    irq_enable;
+};
+
+static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
+{
+       rbuff[0] = bin2bcd(tm->tm_sec);
+       rbuff[1] = bin2bcd(tm->tm_min);
+       rbuff[2] = bin2bcd(tm->tm_hour);
+       rbuff[3] = bin2bcd(tm->tm_mday);
+       rbuff[4] = bin2bcd(tm->tm_mon);
+       rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900));
+}
+
+static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm)
+{
+       tm->tm_sec = bcd2bin(rbuff[0] & 0x7F);
+       tm->tm_min = bcd2bin(rbuff[1] & 0x7F);
+       tm->tm_hour = bcd2bin(rbuff[2] & 0x3F);
+       tm->tm_mday = bcd2bin(rbuff[3] & 0x3F);
+       tm->tm_mon = bcd2bin(rbuff[4] & 0x1F);
+       tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F);
+       return;
+}
+
+static int as3722_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+       struct as3722 *as3722 = as3722_rtc->as3722;
+       u8 as_time_array[6];
+       int ret;
+
+       ret = as3722_block_read(as3722, AS3722_RTC_SECOND_REG,
+                       6, as_time_array);
+       if (ret < 0) {
+               dev_err(dev, "RTC_SECOND reg block read failed %d\n", ret);
+               return ret;
+       }
+       as3722_reg_to_time(as_time_array, tm);
+       return 0;
+}
+
+static int as3722_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+       struct as3722 *as3722 = as3722_rtc->as3722;
+       u8 as_time_array[6];
+       int ret;
+
+       if (tm->tm_year < (AS3722_RTC_START_YEAR - 1900))
+               return -EINVAL;
+
+       as3722_time_to_reg(as_time_array, tm);
+       ret = as3722_block_write(as3722, AS3722_RTC_SECOND_REG, 6,
+                       as_time_array);
+       if (ret < 0)
+               dev_err(dev, "RTC_SECOND reg block write failed %d\n", ret);
+       return ret;
+}
+
+static int as3722_rtc_alarm_irq_enable(struct device *dev,
+               unsigned int enabled)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+
+       if (enabled && !as3722_rtc->irq_enable) {
+               enable_irq(as3722_rtc->alarm_irq);
+               as3722_rtc->irq_enable = true;
+       } else if (!enabled && as3722_rtc->irq_enable)  {
+               disable_irq(as3722_rtc->alarm_irq);
+               as3722_rtc->irq_enable = false;
+       }
+       return 0;
+}
+
+static int as3722_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+       struct as3722 *as3722 = as3722_rtc->as3722;
+       u8 as_time_array[6];
+       int ret;
+
+       ret = as3722_block_read(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
+                       as_time_array);
+       if (ret < 0) {
+               dev_err(dev, "RTC_ALARM_SECOND block read failed %d\n", ret);
+               return ret;
+       }
+
+       as3722_reg_to_time(as_time_array, &alrm->time);
+       return 0;
+}
+
+static int as3722_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+       struct as3722 *as3722 = as3722_rtc->as3722;
+       u8 as_time_array[6];
+       int ret;
+
+       if (alrm->time.tm_year < (AS3722_RTC_START_YEAR - 1900))
+               return -EINVAL;
+
+       ret = as3722_rtc_alarm_irq_enable(dev, 0);
+       if (ret < 0) {
+               dev_err(dev, "Disable RTC alarm failed\n");
+               return ret;
+       }
+
+       as3722_time_to_reg(as_time_array, &alrm->time);
+       ret = as3722_block_write(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
+                       as_time_array);
+       if (ret < 0) {
+               dev_err(dev, "RTC_ALARM_SECOND block write failed %d\n", ret);
+               return ret;
+       }
+
+       if (alrm->enabled)
+               ret = as3722_rtc_alarm_irq_enable(dev, alrm->enabled);
+       return ret;
+}
+
+static irqreturn_t as3722_alarm_irq(int irq, void *data)
+{
+       struct as3722_rtc *as3722_rtc = data;
+
+       rtc_update_irq(as3722_rtc->rtc, 1, RTC_IRQF | RTC_AF);
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops as3722_rtc_ops = {
+       .read_time = as3722_rtc_read_time,
+       .set_time = as3722_rtc_set_time,
+       .read_alarm = as3722_rtc_read_alarm,
+       .set_alarm = as3722_rtc_set_alarm,
+       .alarm_irq_enable = as3722_rtc_alarm_irq_enable,
+};
+
+static int as3722_rtc_probe(struct platform_device *pdev)
+{
+       struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
+       struct as3722_rtc *as3722_rtc;
+       int ret;
+
+       as3722_rtc = devm_kzalloc(&pdev->dev, sizeof(*as3722_rtc), GFP_KERNEL);
+       if (!as3722_rtc)
+               return -ENOMEM;
+
+       as3722_rtc->as3722 = as3722;
+       as3722_rtc->dev = &pdev->dev;
+       platform_set_drvdata(pdev, as3722_rtc);
+
+       /* Enable the RTC to make sure it is running. */
+       ret = as3722_update_bits(as3722, AS3722_RTC_CONTROL_REG,
+                       AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN,
+                       AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "RTC_CONTROL reg write failed: %d\n", ret);
+               return ret;
+       }
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       as3722_rtc->rtc = rtc_device_register("as3722", &pdev->dev,
+                               &as3722_rtc_ops, THIS_MODULE);
+       if (IS_ERR(as3722_rtc->rtc)) {
+               ret = PTR_ERR(as3722_rtc->rtc);
+               dev_err(&pdev->dev, "RTC register failed: %d\n", ret);
+               return ret;
+       }
+
+       as3722_rtc->alarm_irq = platform_get_irq(pdev, 0);
+       dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
+
+       ret = request_threaded_irq(as3722_rtc->alarm_irq, NULL,
+                       as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
+                       "rtc-alarm", as3722_rtc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
+                               as3722_rtc->alarm_irq, ret);
+               goto scrub;
+       }
+       disable_irq(as3722_rtc->alarm_irq);
+       return 0;
+scrub:
+       rtc_device_unregister(as3722_rtc->rtc);
+       return ret;
+}
+
+static int as3722_rtc_remove(struct platform_device *pdev)
+{
+       struct as3722_rtc *as3722_rtc = platform_get_drvdata(pdev);
+
+       free_irq(as3722_rtc->alarm_irq, as3722_rtc);
+       rtc_device_unregister(as3722_rtc->rtc);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int as3722_rtc_suspend(struct device *dev)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(as3722_rtc->alarm_irq);
+
+       return 0;
+}
+
+static int as3722_rtc_resume(struct device *dev)
+{
+       struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(as3722_rtc->alarm_irq);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops as3722_rtc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(as3722_rtc_suspend, as3722_rtc_resume)
+};
+
+static struct platform_driver as3722_rtc_driver = {
+       .probe = as3722_rtc_probe,
+       .remove = as3722_rtc_remove,
+       .driver = {
+               .name = "as3722-rtc",
+               .pm = &as3722_rtc_pm_ops,
+       },
+};
+module_platform_driver(as3722_rtc_driver);
+
+MODULE_DESCRIPTION("RTC driver for AS3722 PMICs");
+MODULE_ALIAS("platform:as3722-rtc");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL");
index 741892632ae09ef4c561e6ee0801d6ea0cec435f..8b2cd8a5a2ffe3d5928d2bc7f026f3fcceaa1dca 100644 (file)
@@ -376,7 +376,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       at91_rtc_regs = ioremap(regs->start, resource_size(regs));
+       at91_rtc_regs = devm_ioremap(&pdev->dev, regs->start,
+                                    resource_size(regs));
        if (!at91_rtc_regs) {
                dev_err(&pdev->dev, "failed to map registers, aborting.\n");
                return -ENOMEM;
@@ -390,12 +391,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
 
-       ret = request_irq(irq, at91_rtc_interrupt,
+       ret = devm_request_irq(&pdev->dev, irq, at91_rtc_interrupt,
                                IRQF_SHARED,
                                "at91_rtc", pdev);
        if (ret) {
                dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);
-               goto err_unmap;
+               return ret;
        }
 
        /* cpu init code should really have flagged this device as
@@ -404,23 +405,14 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
        if (!device_can_wakeup(&pdev->dev))
                device_init_wakeup(&pdev->dev, 1);
 
-       rtc = rtc_device_register(pdev->name, &pdev->dev,
+       rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                                &at91_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               goto err_free_irq;
-       }
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
        platform_set_drvdata(pdev, rtc);
 
        dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
        return 0;
-
-err_free_irq:
-       free_irq(irq, pdev);
-err_unmap:
-       iounmap(at91_rtc_regs);
-
-       return ret;
 }
 
 /*
@@ -428,16 +420,10 @@ err_unmap:
  */
 static int __exit at91_rtc_remove(struct platform_device *pdev)
 {
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
-
        /* Disable all interrupts */
        at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
-       free_irq(irq, pdev);
-
-       rtc_device_unregister(rtc);
-       iounmap(at91_rtc_regs);
 
        return 0;
 }
index 24e733c98f8b69dd13b0b51ef4eab968068a4b85..f14876256a4a5d242695746355149703ed743003 100644 (file)
@@ -595,7 +595,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
 static int INITSECTION
 cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 {
-       struct cmos_rtc_board_info      *info = dev->platform_data;
+       struct cmos_rtc_board_info      *info = dev_get_platdata(dev);
        int                             retval = 0;
        unsigned char                   rtc_control;
        unsigned                        address_space;
@@ -789,7 +789,6 @@ static void __exit cmos_do_remove(struct device *dev)
        cmos->iomem = NULL;
 
        cmos->dev = NULL;
-       dev_set_drvdata(dev, NULL);
 }
 
 #ifdef CONFIG_PM
index e00642b61076e06f01971a5988cbbbcc53aebcba..48cb2ac3bd3ea87e85defd639fb027755dbf3c1c 100644 (file)
@@ -278,7 +278,7 @@ static int da9055_rtc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        rtc->da9055 = dev_get_drvdata(pdev->dev.parent);
-       pdata = rtc->da9055->dev->platform_data;
+       pdata = dev_get_platdata(rtc->da9055->dev);
        platform_set_drvdata(pdev, rtc);
 
        ret = da9055_rtc_device_init(rtc->da9055, pdata);
index dd6170acde95063b8253c837508cf429e5d6753a..80f323731ee2cdac987c963692d49be61841bbb1 100644 (file)
@@ -606,7 +606,7 @@ static int ds1305_probe(struct spi_device *spi)
        struct ds1305                   *ds1305;
        int                             status;
        u8                              addr, value;
-       struct ds1305_platform_data     *pdata = spi->dev.platform_data;
+       struct ds1305_platform_data     *pdata = dev_get_platdata(&spi->dev);
        bool                            write_ctrl = false;
 
        /* Sanity check board setup data.  This may be hooked up
index ca18fd1433b3db9e61ade3acb62dacc7dcee779f..4e75345a559a8eda0a5154406426c27f6cb6bca8 100644 (file)
@@ -670,9 +670,9 @@ static int ds1307_probe(struct i2c_client *client,
        int                     tmp;
        const struct chip_desc  *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
-       int                     want_irq = false;
+       bool                    want_irq = false;
        unsigned char           *buf;
-       struct ds1307_platform_data *pdata = client->dev.platform_data;
+       struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
        static const int        bbsqi_bitpos[] = {
                [ds_1337] = 0,
                [ds_1339] = DS1339_BIT_BBSQI,
@@ -956,7 +956,7 @@ read_rtc:
                                        GFP_KERNEL);
                if (!ds1307->nvram) {
                        err = -ENOMEM;
-                       goto exit;
+                       goto err_irq;
                }
                ds1307->nvram->attr.name = "nvram";
                ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
@@ -967,13 +967,15 @@ read_rtc:
                ds1307->nvram_offset = chip->nvram_offset;
                err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram);
                if (err)
-                       goto exit;
+                       goto err_irq;
                set_bit(HAS_NVRAM, &ds1307->flags);
                dev_info(&client->dev, "%zu bytes nvram\n", ds1307->nvram->size);
        }
 
        return 0;
 
+err_irq:
+       free_irq(client->irq, client);
 exit:
        return err;
 }
index 2ca5a23aba8a15c86baecbf0ec0d1417bd244cbb..fc209dc4e245d90bfdaf045ac9d2ba4c62fd8102 100644 (file)
@@ -224,7 +224,7 @@ static const struct rtc_class_ops ds2404_rtc_ops = {
 
 static int rtc_probe(struct platform_device *pdev)
 {
-       struct ds2404_platform_data *pdata = pdev->dev.platform_data;
+       struct ds2404_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct ds2404 *chip;
        int retval = -EBUSY;
 
index 580e7b56bde87dd22795dceb73d2168bdcd78957..5e4f5dc40ba5db40dd3624bfc2ad88546669c79e 100644 (file)
@@ -42,7 +42,7 @@ struct ep93xx_rtc {
 static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
                                unsigned short *delete)
 {
-       struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+       struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
        unsigned long comp;
 
        comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
@@ -60,7 +60,7 @@ static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
 
 static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+       struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
        unsigned long time;
 
         time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
@@ -71,7 +71,7 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
 {
-       struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+       struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
 
        __raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
        return 0;
index c016ad81767a9d1be4697c267072a124f4398fc6..c3c549d511b964fc7853d2eb4557ea22ab7eecc8 100644 (file)
@@ -144,11 +144,7 @@ isl1208_i2c_validate_client(struct i2c_client *client)
 static int
 isl1208_i2c_get_sr(struct i2c_client *client)
 {
-       int sr = i2c_smbus_read_byte_data(client, ISL1208_REG_SR);
-       if (sr < 0)
-               return -EIO;
-
-       return sr;
+       return i2c_smbus_read_byte_data(client, ISL1208_REG_SR);
 }
 
 static int
@@ -647,10 +643,11 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
                 "chip found, driver version " DRV_VERSION "\n");
 
        if (client->irq > 0) {
-               rc = request_threaded_irq(client->irq, NULL,
-                                         isl1208_rtc_interrupt,
-                                         IRQF_SHARED,
-                                         isl1208_driver.driver.name, client);
+               rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+                                              isl1208_rtc_interrupt,
+                                              IRQF_SHARED,
+                                              isl1208_driver.driver.name,
+                                              client);
                if (!rc) {
                        device_init_wakeup(&client->dev, 1);
                        enable_irq_wake(client->irq);
@@ -662,20 +659,18 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
                }
        }
 
-       rtc = rtc_device_register(isl1208_driver.driver.name,
-                                 &client->dev, &isl1208_rtc_ops,
+       rtc = devm_rtc_device_register(&client->dev, isl1208_driver.driver.name,
+                                 &isl1208_rtc_ops,
                                  THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               rc = PTR_ERR(rtc);
-               goto exit_free_irq;
-       }
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
 
        i2c_set_clientdata(client, rtc);
 
        rc = isl1208_i2c_get_sr(client);
        if (rc < 0) {
                dev_err(&client->dev, "reading status failed\n");
-               goto exit_unregister;
+               return rc;
        }
 
        if (rc & ISL1208_REG_SR_RTCF)
@@ -684,28 +679,15 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
        if (rc)
-               goto exit_unregister;
+               return rc;
 
        return 0;
-
-exit_unregister:
-       rtc_device_unregister(rtc);
-exit_free_irq:
-       if (client->irq)
-               free_irq(client->irq, client);
-
-       return rc;
 }
 
 static int
 isl1208_remove(struct i2c_client *client)
 {
-       struct rtc_device *rtc = i2c_get_clientdata(client);
-
        sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
-       rtc_device_unregister(rtc);
-       if (client->irq)
-               free_irq(client->irq, client);
 
        return 0;
 }
index fcb03291f1454c07b85d005d605cf12617e368b5..11880c1e9dac2b788de81d95b23fb9b46568663c 100644 (file)
@@ -68,7 +68,7 @@ m48t59_mem_readb(struct device *dev, u32 ofs)
 static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        unsigned long flags;
        u8 val;
@@ -111,7 +111,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        unsigned long flags;
        u8 val = 0;
@@ -158,7 +158,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        struct rtc_time *tm = &alrm->time;
        unsigned long flags;
@@ -205,7 +205,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        struct rtc_time *tm = &alrm->time;
        u8 mday, hour, min, sec;
@@ -266,7 +266,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        unsigned long flags;
 
@@ -283,7 +283,7 @@ static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        unsigned long flags;
        u8 val;
@@ -304,7 +304,7 @@ static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
 {
        struct device *dev = (struct device *)dev_id;
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        u8 event;
 
@@ -340,7 +340,7 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        ssize_t cnt = 0;
        unsigned long flags;
@@ -360,7 +360,7 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        ssize_t cnt = 0;
        unsigned long flags;
@@ -385,7 +385,7 @@ static struct bin_attribute m48t59_nvram_attr = {
 
 static int m48t59_rtc_probe(struct platform_device *pdev)
 {
-       struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+       struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct m48t59_private *m48t59 = NULL;
        struct resource *res;
        int ret = -ENOMEM;
index 2d30314fa07f9dff1162c329318b2463ac1bea3b..32f64c942621c03502cb118b551f9174c671cc3b 100644 (file)
@@ -46,7 +46,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        unsigned char reg;
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t86_ops *ops = pdev->dev.platform_data;
+       struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
 
        reg = ops->readbyte(M48T86_REG_B);
 
@@ -84,7 +84,7 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        unsigned char reg;
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t86_ops *ops = pdev->dev.platform_data;
+       struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
 
        reg = ops->readbyte(M48T86_REG_B);
 
@@ -123,7 +123,7 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
 {
        unsigned char reg;
        struct platform_device *pdev = to_platform_device(dev);
-       struct m48t86_ops *ops = pdev->dev.platform_data;
+       struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
 
        reg = ops->readbyte(M48T86_REG_B);
 
@@ -147,7 +147,7 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
 static int m48t86_rtc_probe(struct platform_device *dev)
 {
        unsigned char reg;
-       struct m48t86_ops *ops = dev->dev.platform_data;
+       struct m48t86_ops *ops = dev_get_platdata(&dev->dev);
        struct rtc_device *rtc;
 
        rtc = devm_rtc_device_register(&dev->dev, "m48t86",
index 55969b1b771a344a69125e2d517f8a6cdfc8f335..4804985b876e850572d07c928e9913d8bd31175b 100644 (file)
@@ -164,14 +164,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 
 static int max6900_i2c_clear_write_protect(struct i2c_client *client)
 {
-       int rc;
-       rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
-       if (rc < 0) {
-               dev_err(&client->dev, "%s: control register write failed\n",
-                       __func__);
-               return -EIO;
-       }
-       return 0;
+       return i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
 }
 
 static int
index 315209d9b40780fe1012faed158da21d0cd58570..e2436d140175a109907e55eacafeb1906105748d 100644 (file)
@@ -380,7 +380,6 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
 cleanup1:
        rtc_device_unregister(mrst_rtc.rtc);
 cleanup0:
-       dev_set_drvdata(dev, NULL);
        mrst_rtc.dev = NULL;
        release_mem_region(iomem->start, resource_size(iomem));
        dev_err(dev, "rtc-mrst: unable to initialise\n");
@@ -412,7 +411,6 @@ static void rtc_mrst_do_remove(struct device *dev)
        mrst->iomem = NULL;
 
        mrst->dev = NULL;
-       dev_set_drvdata(dev, NULL);
 }
 
 #ifdef CONFIG_PM
index c7d97ee59327a7bec079b7ab452fdbbb45728b56..26de5f8c2ae43379811f47cc39dd23d9ed40924d 100644 (file)
@@ -553,7 +553,7 @@ static struct platform_driver omap_rtc_driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
                .pm     = &omap_rtc_pm_ops,
-               .of_match_table = of_match_ptr(omap_rtc_of_match),
+               .of_match_table = omap_rtc_of_match,
        },
        .id_table       = omap_rtc_devtype,
 };
index 1725b5090e33d1ea8a768c07f65302f0b61831d7..d1953bb244c599ebd02ea2c3ce8da20171626820 100644 (file)
@@ -327,7 +327,7 @@ kfree_exit:
 
 static int pcf2123_remove(struct spi_device *spi)
 {
-       struct pcf2123_plat_data *pdata = spi->dev.platform_data;
+       struct pcf2123_plat_data *pdata = dev_get_platdata(&spi->dev);
        int i;
 
        if (pdata) {
index 22bacdbf9139dce42e82754ec9de7c061dea755e..f85a1a93e669f9e14d4f68ab1a7040662eb60804 100644 (file)
@@ -106,7 +106,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
        if (ret)
                goto err_req;
 
-       rtc = kmalloc(sizeof(*rtc), GFP_KERNEL);
+       rtc = devm_kzalloc(&dev->dev, sizeof(*rtc), GFP_KERNEL);
        if (!rtc) {
                ret = -ENOMEM;
                goto err_rtc;
@@ -115,7 +115,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
        rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
        if (!rtc->base) {
                ret = -ENOMEM;
-               goto err_map;
+               goto err_rtc;
        }
 
        __raw_writel(0, rtc->base + RTC_CR);
@@ -141,8 +141,6 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
        free_irq(dev->irq[0], rtc);
  err_irq:
        iounmap(rtc->base);
- err_map:
-       kfree(rtc);
  err_rtc:
        amba_release_regions(dev);
  err_req:
@@ -153,14 +151,11 @@ static int pl030_remove(struct amba_device *dev)
 {
        struct pl030_rtc *rtc = amba_get_drvdata(dev);
 
-       amba_set_drvdata(dev, NULL);
-
        writel(0, rtc->base + RTC_CR);
 
        free_irq(dev->irq[0], rtc);
        rtc_device_unregister(rtc->rtc);
        iounmap(rtc->base);
-       kfree(rtc);
        amba_release_regions(dev);
 
        return 0;
index e3b25712b6591906aff9633e98d5c82f4feba351..99181fff88fd6f4e3518a1e2b3c166b674b59305 100644 (file)
@@ -305,7 +305,6 @@ static int pl031_remove(struct amba_device *adev)
 {
        struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
 
-       amba_set_drvdata(adev, NULL);
        free_irq(adev->irq[0], ldata);
        rtc_device_unregister(ldata->rtc);
        iounmap(ldata->base);
@@ -391,7 +390,6 @@ out_no_irq:
        rtc_device_unregister(ldata->rtc);
 out_no_rtc:
        iounmap(ldata->base);
-       amba_set_drvdata(adev, NULL);
 out_no_remap:
        kfree(ldata);
 out:
index 402732cfb32a5574f6fda08f5637ba04a6d1fb0d..1ecfe3bd92ac8c460885114689172ebccbd22b2f 100644 (file)
@@ -53,11 +53,11 @@ static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
 }
 
 /* Update control registers */
-static void puv3_rtc_setaie(int to)
+static void puv3_rtc_setaie(struct device *dev, int to)
 {
        unsigned int tmp;
 
-       pr_debug("%s: aie=%d\n", __func__, to);
+       dev_dbg(dev, "%s: aie=%d\n", __func__, to);
 
        tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
 
@@ -71,7 +71,7 @@ static int puv3_rtc_setpie(struct device *dev, int enabled)
 {
        unsigned int tmp;
 
-       pr_debug("%s: pie=%d\n", __func__, enabled);
+       dev_debug(dev, "%s: pie=%d\n", __func__, enabled);
 
        spin_lock_irq(&puv3_rtc_pie_lock);
        tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
@@ -90,7 +90,7 @@ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 {
        rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
 
-       pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+       dev_dbg(dev, "read time %02x.%02x.%02x %02x/%02x/%02x\n",
                 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
                 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
 
@@ -101,7 +101,7 @@ static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
 {
        unsigned long rtc_count = 0;
 
-       pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+       dev_dbg(dev, "set time %02d.%02d.%02d %02d/%02d/%02d\n",
                 tm->tm_year, tm->tm_mon, tm->tm_mday,
                 tm->tm_hour, tm->tm_min, tm->tm_sec);
 
@@ -119,7 +119,7 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
 
-       pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+       dev_dbg(dev, "read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
                 alrm->enabled,
                 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
                 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
@@ -132,7 +132,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_time *tm = &alrm->time;
        unsigned long rtcalarm_count = 0;
 
-       pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
+       dev_dbg(dev, "puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
                 alrm->enabled,
                 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
                 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
@@ -140,7 +140,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        rtc_tm_to_time(tm, &rtcalarm_count);
        writel(rtcalarm_count, RTC_RTAR);
 
-       puv3_rtc_setaie(alrm->enabled);
+       puv3_rtc_setaie(&dev->dev, alrm->enabled);
 
        if (alrm->enabled)
                enable_irq_wake(puv3_rtc_alarmno);
@@ -227,7 +227,7 @@ static int puv3_rtc_remove(struct platform_device *dev)
        rtc_device_unregister(rtc);
 
        puv3_rtc_setpie(&dev->dev, 0);
-       puv3_rtc_setaie(0);
+       puv3_rtc_setaie(&dev->dev, 0);
 
        release_resource(puv3_rtc_mem);
        kfree(puv3_rtc_mem);
@@ -241,7 +241,7 @@ static int puv3_rtc_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
 
-       pr_debug("%s: probe=%p\n", __func__, pdev);
+       dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev);
 
        /* find the IRQs */
        puv3_rtc_tickno = platform_get_irq(pdev, 1);
@@ -256,7 +256,7 @@ static int puv3_rtc_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
+       dev_dbg(&pdev->dev, "PKUnity_rtc: tick irq %d, alarm irq %d\n",
                 puv3_rtc_tickno, puv3_rtc_alarmno);
 
        /* get the memory region */
index f7a90a116a39bcc0dda39a8c31ec866a0dde29fb..090a101c1c813813fc0aa26497e251dbd65d984a 100644 (file)
@@ -64,7 +64,7 @@ static int
 rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct spi_device *spi = to_spi_device(dev);
-       struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+       struct rs5c348_plat_data *pdata = dev_get_platdata(&spi->dev);
        u8 txbuf[5+7], *txp;
        int ret;
 
@@ -100,7 +100,7 @@ static int
 rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct spi_device *spi = to_spi_device(dev);
-       struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+       struct rs5c348_plat_data *pdata = dev_get_platdata(&spi->dev);
        u8 txbuf[5], rxbuf[7];
        int ret;
 
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
new file mode 100644 (file)
index 0000000..b7fd02b
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ *     http://www.samsung.com
+ *
+ *  Copyright (C) 2013 Google, Inc
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/bcd.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/irq.h>
+#include <linux/mfd/samsung/rtc.h>
+
+struct s5m_rtc_info {
+       struct device *dev;
+       struct sec_pmic_dev *s5m87xx;
+       struct regmap *rtc;
+       struct rtc_device *rtc_dev;
+       int irq;
+       int device_type;
+       int rtc_24hr_mode;
+       bool wtsr_smpl;
+};
+
+static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm,
+                              int rtc_24hr_mode)
+{
+       tm->tm_sec = data[RTC_SEC] & 0x7f;
+       tm->tm_min = data[RTC_MIN] & 0x7f;
+       if (rtc_24hr_mode) {
+               tm->tm_hour = data[RTC_HOUR] & 0x1f;
+       } else {
+               tm->tm_hour = data[RTC_HOUR] & 0x0f;
+               if (data[RTC_HOUR] & HOUR_PM_MASK)
+                       tm->tm_hour += 12;
+       }
+
+       tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f);
+       tm->tm_mday = data[RTC_DATE] & 0x1f;
+       tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
+       tm->tm_year = (data[RTC_YEAR1] & 0x7f) + 100;
+       tm->tm_yday = 0;
+       tm->tm_isdst = 0;
+}
+
+static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+       data[RTC_SEC] = tm->tm_sec;
+       data[RTC_MIN] = tm->tm_min;
+
+       if (tm->tm_hour >= 12)
+               data[RTC_HOUR] = tm->tm_hour | HOUR_PM_MASK;
+       else
+               data[RTC_HOUR] = tm->tm_hour & ~HOUR_PM_MASK;
+
+       data[RTC_WEEKDAY] = 1 << tm->tm_wday;
+       data[RTC_DATE] = tm->tm_mday;
+       data[RTC_MONTH] = tm->tm_mon + 1;
+       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",
+                      1900 + tm->tm_year);
+               return -EINVAL;
+       } else {
+               return 0;
+       }
+}
+
+static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
+{
+       int ret;
+       unsigned int data;
+
+       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       if (ret < 0) {
+               dev_err(info->dev, "failed to read update reg(%d)\n", ret);
+               return ret;
+       }
+
+       data |= RTC_TIME_EN_MASK;
+       data |= RTC_UDR_MASK;
+
+       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       if (ret < 0) {
+               dev_err(info->dev, "failed to write update reg(%d)\n", ret);
+               return ret;
+       }
+
+       do {
+               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       } while ((data & RTC_UDR_MASK) && !ret);
+
+       return ret;
+}
+
+static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
+{
+       int ret;
+       unsigned int data;
+
+       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to read update reg(%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       data &= ~RTC_TIME_EN_MASK;
+       data |= RTC_UDR_MASK;
+
+       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write update reg(%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       do {
+               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       } while ((data & RTC_UDR_MASK) && !ret);
+
+       return ret;
+}
+
+static void s5m8763_data_to_tm(u8 *data, struct rtc_time *tm)
+{
+       tm->tm_sec = bcd2bin(data[RTC_SEC]);
+       tm->tm_min = bcd2bin(data[RTC_MIN]);
+
+       if (data[RTC_HOUR] & HOUR_12) {
+               tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f);
+               if (data[RTC_HOUR] & HOUR_PM)
+                       tm->tm_hour += 12;
+       } else {
+               tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
+       }
+
+       tm->tm_wday = data[RTC_WEEKDAY] & 0x07;
+       tm->tm_mday = bcd2bin(data[RTC_DATE]);
+       tm->tm_mon = bcd2bin(data[RTC_MONTH]);
+       tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100;
+       tm->tm_year -= 1900;
+}
+
+static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+       data[RTC_SEC] = bin2bcd(tm->tm_sec);
+       data[RTC_MIN] = bin2bcd(tm->tm_min);
+       data[RTC_HOUR] = bin2bcd(tm->tm_hour);
+       data[RTC_WEEKDAY] = tm->tm_wday;
+       data[RTC_DATE] = bin2bcd(tm->tm_mday);
+       data[RTC_MONTH] = bin2bcd(tm->tm_mon);
+       data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100);
+       data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100);
+}
+
+static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[8];
+       int ret;
+
+       ret = regmap_bulk_read(info->rtc, SEC_RTC_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       switch (info->device_type) {
+       case S5M8763X:
+               s5m8763_data_to_tm(data, tm);
+               break;
+
+       case S5M8767X:
+               s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+               1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+
+       return rtc_valid_tm(tm);
+}
+
+static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[8];
+       int ret = 0;
+
+       switch (info->device_type) {
+       case S5M8763X:
+               s5m8763_tm_to_data(tm, data);
+               break;
+       case S5M8767X:
+               ret = s5m8767_tm_to_data(tm, data);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+               1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+
+       ret = regmap_raw_write(info->rtc, SEC_RTC_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       ret = s5m8767_rtc_set_time_reg(info);
+
+       return ret;
+}
+
+static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[8];
+       unsigned int val;
+       int ret, i;
+
+       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       switch (info->device_type) {
+       case S5M8763X:
+               s5m8763_data_to_tm(data, &alrm->time);
+               ret = regmap_read(info->rtc, SEC_ALARM0_CONF, &val);
+               if (ret < 0)
+                       return ret;
+
+               alrm->enabled = !!val;
+
+               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       case S5M8767X:
+               s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+               dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+                       1900 + alrm->time.tm_year, 1 + alrm->time.tm_mon,
+                       alrm->time.tm_mday, alrm->time.tm_hour,
+                       alrm->time.tm_min, alrm->time.tm_sec,
+                       alrm->time.tm_wday);
+
+               alrm->enabled = 0;
+               for (i = 0; i < 7; i++) {
+                       if (data[i] & ALARM_ENABLE_MASK) {
+                               alrm->enabled = 1;
+                               break;
+                       }
+               }
+
+               alrm->pending = 0;
+               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               if (ret < 0)
+                       return ret;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (val & ALARM0_STATUS)
+               alrm->pending = 1;
+       else
+               alrm->pending = 0;
+
+       return 0;
+}
+
+static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
+{
+       u8 data[8];
+       int ret, i;
+       struct rtc_time tm;
+
+       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode);
+       dev_dbg(info->dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+               1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday);
+
+       switch (info->device_type) {
+       case S5M8763X:
+               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, 0);
+               break;
+
+       case S5M8767X:
+               for (i = 0; i < 7; i++)
+                       data[i] &= ~ALARM_ENABLE_MASK;
+
+               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               if (ret < 0)
+                       return ret;
+
+               ret = s5m8767_rtc_set_alarm_reg(info);
+
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
+{
+       int ret;
+       u8 data[8];
+       u8 alarm0_conf;
+       struct rtc_time tm;
+
+       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode);
+       dev_dbg(info->dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+               1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday);
+
+       switch (info->device_type) {
+       case S5M8763X:
+               alarm0_conf = 0x77;
+               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, alarm0_conf);
+               break;
+
+       case S5M8767X:
+               data[RTC_SEC] |= ALARM_ENABLE_MASK;
+               data[RTC_MIN] |= ALARM_ENABLE_MASK;
+               data[RTC_HOUR] |= ALARM_ENABLE_MASK;
+               data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
+               if (data[RTC_DATE] & 0x1f)
+                       data[RTC_DATE] |= ALARM_ENABLE_MASK;
+               if (data[RTC_MONTH] & 0xf)
+                       data[RTC_MONTH] |= ALARM_ENABLE_MASK;
+               if (data[RTC_YEAR1] & 0x7f)
+                       data[RTC_YEAR1] |= ALARM_ENABLE_MASK;
+
+               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               if (ret < 0)
+                       return ret;
+               ret = s5m8767_rtc_set_alarm_reg(info);
+
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[8];
+       int ret;
+
+       switch (info->device_type) {
+       case S5M8763X:
+               s5m8763_tm_to_data(&alrm->time, data);
+               break;
+
+       case S5M8767X:
+               s5m8767_tm_to_data(&alrm->time, data);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
+               1900 + alrm->time.tm_year, 1 + alrm->time.tm_mon,
+               alrm->time.tm_mday, alrm->time.tm_hour, alrm->time.tm_min,
+               alrm->time.tm_sec, alrm->time.tm_wday);
+
+       ret = s5m_rtc_stop_alarm(info);
+       if (ret < 0)
+               return ret;
+
+       ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+       if (ret < 0)
+               return ret;
+
+       ret = s5m8767_rtc_set_alarm_reg(info);
+       if (ret < 0)
+               return ret;
+
+       if (alrm->enabled)
+               ret = s5m_rtc_start_alarm(info);
+
+       return ret;
+}
+
+static int s5m_rtc_alarm_irq_enable(struct device *dev,
+                                   unsigned int enabled)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+
+       if (enabled)
+               return s5m_rtc_start_alarm(info);
+       else
+               return s5m_rtc_stop_alarm(info);
+}
+
+static irqreturn_t s5m_rtc_alarm_irq(int irq, void *data)
+{
+       struct s5m_rtc_info *info = data;
+
+       rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops s5m_rtc_ops = {
+       .read_time = s5m_rtc_read_time,
+       .set_time = s5m_rtc_set_time,
+       .read_alarm = s5m_rtc_read_alarm,
+       .set_alarm = s5m_rtc_set_alarm,
+       .alarm_irq_enable = s5m_rtc_alarm_irq_enable,
+};
+
+static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
+{
+       int ret;
+       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+                                WTSR_ENABLE_MASK,
+                                enable ? WTSR_ENABLE_MASK : 0);
+       if (ret < 0)
+               dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
+                       __func__, ret);
+}
+
+static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable)
+{
+       int ret;
+       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+                                SMPL_ENABLE_MASK,
+                                enable ? SMPL_ENABLE_MASK : 0);
+       if (ret < 0)
+               dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
+                       __func__, ret);
+}
+
+static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
+{
+       u8 data[2];
+       unsigned int tp_read;
+       int ret;
+       struct rtc_time tm;
+
+       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &tp_read);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to read control reg(%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       /* Set RTC control register : Binary mode, 24hour mode */
+       data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+       data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+
+       info->rtc_24hr_mode = 1;
+       ret = regmap_raw_write(info->rtc, SEC_ALARM0_CONF, data, 2);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       /* In first boot time, Set rtc time to 1/1/2012 00:00:00(SUN) */
+       if ((tp_read & RTC_TCON_MASK) == 0) {
+               dev_dbg(info->dev, "rtc init\n");
+               tm.tm_sec = 0;
+               tm.tm_min = 0;
+               tm.tm_hour = 0;
+               tm.tm_wday = 0;
+               tm.tm_mday = 1;
+               tm.tm_mon = 0;
+               tm.tm_year = 112;
+               tm.tm_yday = 0;
+               tm.tm_isdst = 0;
+               ret = s5m_rtc_set_time(info->dev, &tm);
+       }
+
+       ret = regmap_update_bits(info->rtc, SEC_RTC_UDR_CON,
+                                RTC_TCON_MASK, tp_read | RTC_TCON_MASK);
+       if (ret < 0)
+               dev_err(info->dev, "%s: fail to update TCON reg(%d)\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+static int s5m_rtc_probe(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
+       struct sec_platform_data *pdata = s5m87xx->pdata;
+       struct s5m_rtc_info *info;
+       int ret;
+
+       if (!pdata) {
+               dev_err(pdev->dev.parent, "Platform data not supplied\n");
+               return -ENODEV;
+       }
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->dev = &pdev->dev;
+       info->s5m87xx = s5m87xx;
+       info->rtc = s5m87xx->rtc;
+       info->device_type = s5m87xx->device_type;
+       info->wtsr_smpl = s5m87xx->wtsr_smpl;
+
+       switch (pdata->device_type) {
+       case S5M8763X:
+               info->irq = s5m87xx->irq_base + S5M8763_IRQ_ALARM0;
+               break;
+
+       case S5M8767X:
+               info->irq = s5m87xx->irq_base + S5M8767_IRQ_RTCA1;
+               break;
+
+       default:
+               ret = -EINVAL;
+               dev_err(&pdev->dev, "Unsupported device type: %d\n", ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, info);
+
+       ret = s5m8767_rtc_init_reg(info);
+
+       if (info->wtsr_smpl) {
+               s5m_rtc_enable_wtsr(info, true);
+               s5m_rtc_enable_smpl(info, true);
+       }
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc",
+                                                &s5m_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(info->rtc_dev))
+               return PTR_ERR(info->rtc_dev);
+
+       ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
+                                       s5m_rtc_alarm_irq, 0, "rtc-alarm0",
+                                       info);
+       if (ret < 0)
+               dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+                       info->irq, ret);
+
+       return ret;
+}
+
+static void s5m_rtc_shutdown(struct platform_device *pdev)
+{
+       struct s5m_rtc_info *info = platform_get_drvdata(pdev);
+       int i;
+       unsigned int val = 0;
+       if (info->wtsr_smpl) {
+               for (i = 0; i < 3; i++) {
+                       s5m_rtc_enable_wtsr(info, false);
+                       regmap_read(info->rtc, SEC_WTSR_SMPL_CNTL, &val);
+                       pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val);
+                       if (val & WTSR_ENABLE_MASK)
+                               pr_emerg("%s: fail to disable WTSR\n",
+                                        __func__);
+                       else {
+                               pr_info("%s: success to disable WTSR\n",
+                                       __func__);
+                               break;
+                       }
+               }
+       }
+       /* Disable SMPL when power off */
+       s5m_rtc_enable_smpl(info, false);
+}
+
+static const struct platform_device_id s5m_rtc_id[] = {
+       { "s5m-rtc", 0 },
+};
+
+static struct platform_driver s5m_rtc_driver = {
+       .driver         = {
+               .name   = "s5m-rtc",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = s5m_rtc_probe,
+       .shutdown       = s5m_rtc_shutdown,
+       .id_table       = s5m_rtc_id,
+};
+
+module_platform_driver(s5m_rtc_driver);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("Samsung S5M RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s5m-rtc");
index 6d87e26355a3020b25a4242f7459c1e0cb98244b..d0d2b047658beeae9509da815065a7b01e30055a 100644 (file)
@@ -649,8 +649,9 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        clk_enable(rtc->clk);
 
        rtc->capabilities = RTC_DEF_CAPABILITIES;
-       if (pdev->dev.platform_data) {
-               struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data;
+       if (dev_get_platdata(&pdev->dev)) {
+               struct sh_rtc_platform_info *pinfo =
+                       dev_get_platdata(&pdev->dev);
 
                /*
                 * Some CPUs have special capabilities in addition to the
index 63460cf80f1b3d6068d915ad9b4707b202b817ef..3eb3642ae299fe66f6fb6bd57db39c8955d2d2f1 100644 (file)
@@ -59,7 +59,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
        unsigned long rtc_alarm, rtc_count;
        struct sirfsoc_rtc_drv *rtcdrv;
 
-       rtcdrv = (struct sirfsoc_rtc_drv *)dev_get_drvdata(dev);
+       rtcdrv = dev_get_drvdata(dev);
 
        local_irq_disable();
 
@@ -94,7 +94,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
 {
        unsigned long rtc_status_reg, rtc_alarm;
        struct sirfsoc_rtc_drv *rtcdrv;
-       rtcdrv = (struct sirfsoc_rtc_drv *)dev_get_drvdata(dev);
+       rtcdrv = dev_get_drvdata(dev);
 
        if (alrm->enabled) {
                rtc_tm_to_time(&(alrm->time), &rtc_alarm);
@@ -157,7 +157,7 @@ static int sirfsoc_rtc_read_time(struct device *dev,
 {
        unsigned long tmp_rtc = 0;
        struct sirfsoc_rtc_drv *rtcdrv;
-       rtcdrv = (struct sirfsoc_rtc_drv *)dev_get_drvdata(dev);
+       rtcdrv = dev_get_drvdata(dev);
        /*
         * This patch is taken from WinCE - Need to validate this for
         * correctness. To work around sirfsoc RTC counter double sync logic
@@ -178,7 +178,7 @@ static int sirfsoc_rtc_set_time(struct device *dev,
 {
        unsigned long rtc_time;
        struct sirfsoc_rtc_drv *rtcdrv;
-       rtcdrv = (struct sirfsoc_rtc_drv *)dev_get_drvdata(dev);
+       rtcdrv = dev_get_drvdata(dev);
 
        rtc_tm_to_time(tm, &rtc_time);
 
@@ -274,7 +274,7 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base);
        if (err) {
                dev_err(&pdev->dev, "unable to find base address of rtc node in dtb\n");
-               goto error;
+               return err;
        }
 
        platform_set_drvdata(pdev, rtcdrv);
@@ -290,7 +290,7 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        rtc_div = ((32768 / RTC_HZ) / 2) - 1;
        sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
 
-       rtcdrv->rtc = rtc_device_register(pdev->name, &(pdev->dev),
+       rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                        &sirfsoc_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtcdrv->rtc)) {
                err = PTR_ERR(rtcdrv->rtc);
@@ -322,24 +322,15 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
                        rtcdrv);
        if (err) {
                dev_err(&pdev->dev, "Unable to register for the SiRF SOC RTC IRQ\n");
-               goto error;
+               return err;
        }
 
        return 0;
-
-error:
-       if (rtcdrv->rtc)
-               rtc_device_unregister(rtcdrv->rtc);
-
-       return err;
 }
 
 static int sirfsoc_rtc_remove(struct platform_device *pdev)
 {
-       struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
-
        device_init_wakeup(&pdev->dev, 0);
-       rtc_device_unregister(rtcdrv->rtc);
 
        return 0;
 }
@@ -373,7 +364,7 @@ static int sirfsoc_rtc_thaw(struct device *dev)
 {
        u32 tmp;
        struct sirfsoc_rtc_drv *rtcdrv;
-       rtcdrv = (struct sirfsoc_rtc_drv *)dev_get_drvdata(dev);
+       rtcdrv = dev_get_drvdata(dev);
 
        /*
         * if resume from snapshot and the rtc power is losed,
@@ -467,7 +458,7 @@ static struct platform_driver sirfsoc_rtc_driver = {
 #ifdef CONFIG_PM
                .pm = &sirfsoc_rtc_pm_ops,
 #endif
-               .of_match_table = of_match_ptr(sirfsoc_rtc_of_match),
+               .of_match_table = sirfsoc_rtc_of_match,
        },
        .probe = sirfsoc_rtc_probe,
        .remove = sirfsoc_rtc_remove,
index 316a342115b28440b804c08031ccb1143f17e260..fa384fe28988f6f27078f80a0a67b390ccf8687b 100644 (file)
@@ -329,7 +329,7 @@ static struct platform_driver snvs_rtc_driver = {
                .name   = "snvs_rtc",
                .owner  = THIS_MODULE,
                .pm     = &snvs_rtc_pm_ops,
-               .of_match_table = of_match_ptr(snvs_dt_ids),
+               .of_match_table = snvs_dt_ids,
        },
        .probe          = snvs_rtc_probe,
 };
index 26019531db15a2f481dc87da6e6c76e085e1a06c..ea96492357b0339c0b01ad18a4505f9418ed6bd5 100644 (file)
@@ -343,7 +343,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
                .name   = "stmp3xxx-rtc",
                .owner  = THIS_MODULE,
                .pm     = &stmp3xxx_rtc_pm_ops,
-               .of_match_table = of_match_ptr(rtc_dt_ids),
+               .of_match_table = rtc_dt_ids,
        },
 };
 
index a9caf043b0ce8716f495d437f3d2be9857b03885..7af00208d637141a8eb18a045b94b6cfa4f5e071 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/tps65910.h>
 
index d07d8982302054cd18cf34d619c6fb0200df9c21..25222cdccdc627d34fd796df41cdd0d8caab7a83 100644 (file)
@@ -303,7 +303,7 @@ static const struct rtc_class_ops v3020_rtc_ops = {
 
 static int rtc_probe(struct platform_device *pdev)
 {
-       struct v3020_platform_data *pdata = pdev->dev.platform_data;
+       struct v3020_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct v3020 *chip;
        int retval = -EBUSY;
        int i;
index 54e104e197e384640c30e18bc8e73dc08b8e2f34..aabc22c587fb49025b47de4de531279832a05efd 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/uaccess.h>
 #include <linux/log2.h>
 
 #include <asm/div64.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 
 MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
index c2d6331fc712c7244a87d33ef1e2d6d3cfa7fdca..df2ef3eba7cd14561c9c58f746d83263c8c93601 100644 (file)
@@ -228,7 +228,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev)
        vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);
        if (vt8500_rtc->irq_alarm < 0) {
                dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
-               return -ENXIO;
+               return vt8500_rtc->irq_alarm;
        }
 
        vt8500_rtc->res = devm_request_mem_region(&pdev->dev,
@@ -296,7 +296,7 @@ static struct platform_driver vt8500_rtc_driver = {
        .driver         = {
                .name   = "vt8500-rtc",
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(wmt_dt_ids),
+               .of_match_table = wmt_dt_ids,
        },
 };
 
index 2870487dd2865ded03738624ec96c094c8623891..35aefa2cdad1797c4ae9f3cf0400fcd1ab59da1a 100644 (file)
 #define LUSTRE_EHOSTUNREACH    113     /* No route to host */
 #define LUSTRE_EALREADY                114     /* Operation already in progress */
 #define LUSTRE_EINPROGRESS     115     /* Operation now in progress */
-#define LUSTRE_ESTALE          116     /* Stale NFS file handle */
+#define LUSTRE_ESTALE          116     /* Stale file handle */
 #define LUSTRE_EUCLEAN         117     /* Structure needs cleaning */
 #define LUSTRE_ENOTNAM         118     /* Not a XENIX named type file */
 #define LUSTRE_ENAVAIL         119     /* No XENIX semaphores available */
index f519da9034b7b5540b872fade72fd2391281fb80..96c4a19b19183b59bcd740053a7618e177b0907e 100644 (file)
@@ -158,14 +158,12 @@ static int pruss_probe(struct platform_device *dev)
        if (pdata->sram_pool) {
                gdev->sram_pool = pdata->sram_pool;
                gdev->sram_vaddr =
-                       gen_pool_alloc(gdev->sram_pool, sram_pool_sz);
+                       (unsigned long)gen_pool_dma_alloc(gdev->sram_pool,
+                                       sram_pool_sz, &gdev->sram_paddr);
                if (!gdev->sram_vaddr) {
                        dev_err(&dev->dev, "Could not allocate SRAM pool\n");
                        goto out_free;
                }
-               gdev->sram_paddr =
-                       gen_pool_virt_to_phys(gdev->sram_pool,
-                                             gdev->sram_vaddr);
        }
 
        gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
index 7e8346ec9cdc32f1a04e0c493e4d859d71efa189..a305caea58eea717fdffaac4c5364552673ad5ae 100644 (file)
@@ -949,9 +949,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
                 * the page.
                 */
                page = virt_to_page(virtual_start);
-               ClearPageReserved(page);
-               init_page_count(page);
-               free_page(virtual_start);
+               __free_reserved_page(page);
 
                virtual_start += PAGE_SIZE;
                mb_freed += PAGE_SIZE / 1024;
index 2cd63507ed74a7ee420f254e8219abe99378ea91..7db5234462d06a2c960ebf958fdddcae1f6db1f8 100644 (file)
@@ -196,7 +196,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
 static int pm860x_backlight_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm860x_backlight_pdata *pdata = pdev->dev.platform_data;
+       struct pm860x_backlight_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct pm860x_backlight_data *data;
        struct backlight_device *bl;
        struct resource *res;
@@ -243,7 +243,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
-       bl = backlight_device_register(name, &pdev->dev, data,
+       bl = devm_backlight_device_register(&pdev->dev, name, &pdev->dev, data,
                                        &pm860x_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
@@ -256,21 +256,10 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        /* read current backlight */
        ret = pm860x_backlight_get_brightness(bl);
        if (ret < 0)
-               goto out_brt;
+               return ret;
 
        backlight_update_status(bl);
        return 0;
-out_brt:
-       backlight_device_unregister(bl);
-       return ret;
-}
-
-static int pm860x_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bl);
-       return 0;
 }
 
 static struct platform_driver pm860x_backlight_driver = {
@@ -279,7 +268,6 @@ static struct platform_driver pm860x_backlight_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pm860x_backlight_probe,
-       .remove         = pm860x_backlight_remove,
 };
 
 module_platform_driver(pm860x_backlight_driver);
index d4a7a351d67c801fc3cb7e36b779f21561882177..5a3eb2ecb525c2b52a2d1f5d8decb688a93bb99d 100644 (file)
@@ -368,12 +368,12 @@ config BACKLIGHT_AAT2870
          If you have a AnalogicTech AAT2870 say Y to enable the
          backlight driver.
 
-config BACKLIGHT_LM3630
-       tristate "Backlight Driver for LM3630"
+config BACKLIGHT_LM3630A
+       tristate "Backlight Driver for LM3630A"
        depends on BACKLIGHT_CLASS_DEVICE && I2C
        select REGMAP_I2C
        help
-         This supports TI LM3630 Backlight Driver
+         This supports TI LM3630A Backlight Driver
 
 config BACKLIGHT_LM3639
        tristate "Backlight Driver for LM3639"
@@ -388,8 +388,8 @@ config BACKLIGHT_LP855X
        tristate "Backlight driver for TI LP855X"
        depends on BACKLIGHT_CLASS_DEVICE && I2C
        help
-         This supports TI LP8550, LP8551, LP8552, LP8553, LP8556 and LP8557
-         backlight driver.
+         This supports TI LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and
+         LP8557 backlight driver.
 
 config BACKLIGHT_LP8788
        tristate "Backlight driver for TI LP8788 MFD"
index 38e1babb194636b7e886347a689d9133e09f4153..bb820024f346df519cc8984078a1bf8fd8a7bf70 100644 (file)
@@ -37,7 +37,7 @@ obj-$(CONFIG_BACKLIGHT_GPIO)          += gpio_backlight.o
 obj-$(CONFIG_BACKLIGHT_HP680)          += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_HP700)          += jornada720_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3533)         += lm3533_bl.o
-obj-$(CONFIG_BACKLIGHT_LM3630)         += lm3630_bl.o
+obj-$(CONFIG_BACKLIGHT_LM3630A)                += lm3630a_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3639)         += lm3639_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO)         += locomolcd.o
 obj-$(CONFIG_BACKLIGHT_LP855X)         += lp855x_bl.o
index c6fc668d623628015c98488b891144074d3b47a2..ee0c0a982e4eebb8be7ebc06fc9866f1c1ac0e66 100644 (file)
@@ -127,7 +127,7 @@ static const struct backlight_ops aat2870_bl_ops = {
 
 static int aat2870_bl_probe(struct platform_device *pdev)
 {
-       struct aat2870_bl_platform_data *pdata = pdev->dev.platform_data;
+       struct aat2870_bl_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct aat2870_bl_driver_data *aat2870_bl;
        struct backlight_device *bd;
        struct backlight_properties props;
@@ -158,8 +158,9 @@ static int aat2870_bl_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
 
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("aat2870-backlight", &pdev->dev,
-                                      aat2870_bl, &aat2870_bl_ops, &props);
+       bd = devm_backlight_device_register(&pdev->dev, "aat2870-backlight",
+                                       &pdev->dev, aat2870_bl, &aat2870_bl_ops,
+                                       &props);
        if (IS_ERR(bd)) {
                dev_err(&pdev->dev,
                        "Failed allocate memory for backlight device\n");
@@ -194,13 +195,11 @@ static int aat2870_bl_probe(struct platform_device *pdev)
        ret = aat2870_bl_update_status(bd);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to initialize\n");
-               goto out_bl_dev_unregister;
+               return ret;
        }
 
        return 0;
 
-out_bl_dev_unregister:
-       backlight_device_unregister(bd);
 out:
        return ret;
 }
@@ -214,8 +213,6 @@ static int aat2870_bl_remove(struct platform_device *pdev)
        bd->props.brightness = 0;
        backlight_update_status(bd);
 
-       backlight_device_unregister(bd);
-
        return 0;
 }
 
index c84701b7ca6e802d4d45a7271fabe665782d0a38..f37097a261a210f1c168def54c2ef22e6fa6e965 100644 (file)
@@ -297,7 +297,7 @@ static int adp5520_bl_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        data->master = pdev->dev.parent;
-       data->pdata = pdev->dev.platform_data;
+       data->pdata = dev_get_platdata(&pdev->dev);
 
        if (data->pdata  == NULL) {
                dev_err(&pdev->dev, "missing platform data\n");
@@ -312,8 +312,9 @@ static int adp5520_bl_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = ADP5020_MAX_BRIGHTNESS;
-       bl = backlight_device_register(pdev->name, data->master, data,
-                                      &adp5520_bl_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, pdev->name,
+                                       data->master, data, &adp5520_bl_ops,
+                                       &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -326,7 +327,7 @@ static int adp5520_bl_probe(struct platform_device *pdev)
 
        if (ret) {
                dev_err(&pdev->dev, "failed to register sysfs\n");
-               backlight_device_unregister(bl);
+               return ret;
        }
 
        platform_set_drvdata(pdev, bl);
@@ -347,8 +348,6 @@ static int adp5520_bl_remove(struct platform_device *pdev)
                sysfs_remove_group(&bl->dev.kobj,
                                &adp5520_bl_attr_group);
 
-       backlight_device_unregister(bl);
-
        return 0;
 }
 
index 75b10f8761276a889bde8be038e23212f8730eba..9d656717d0f784cef243630d559ab93d674c45a8 100644 (file)
@@ -216,7 +216,7 @@ static int adp8860_led_setup(struct adp8860_led *led)
 static int adp8860_led_probe(struct i2c_client *client)
 {
        struct adp8860_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct adp8860_bl *data = i2c_get_clientdata(client);
        struct adp8860_led *led, *led_dat;
        struct led_info *cur_led;
@@ -300,7 +300,7 @@ static int adp8860_led_probe(struct i2c_client *client)
 static int adp8860_led_remove(struct i2c_client *client)
 {
        struct adp8860_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct adp8860_bl *data = i2c_get_clientdata(client);
        int i;
 
@@ -658,7 +658,7 @@ static int adp8860_probe(struct i2c_client *client,
        struct backlight_device *bl;
        struct adp8860_bl *data;
        struct adp8860_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct backlight_properties props;
        uint8_t reg_val;
        int ret;
@@ -711,8 +711,9 @@ static int adp8860_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       bl = backlight_device_register(dev_driver_string(&client->dev),
-                       &client->dev, data, &adp8860_bl_ops, &props);
+       bl = devm_backlight_device_register(&client->dev,
+                               dev_driver_string(&client->dev),
+                               &client->dev, data, &adp8860_bl_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&client->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -728,7 +729,7 @@ static int adp8860_probe(struct i2c_client *client,
 
        if (ret) {
                dev_err(&client->dev, "failed to register sysfs\n");
-               goto out1;
+               return ret;
        }
 
        ret = adp8860_bl_setup(bl);
@@ -751,8 +752,6 @@ out:
        if (data->en_ambl_sens)
                sysfs_remove_group(&data->bl->dev.kobj,
                        &adp8860_bl_attr_group);
-out1:
-       backlight_device_unregister(bl);
 
        return ret;
 }
@@ -770,8 +769,6 @@ static int adp8860_remove(struct i2c_client *client)
                sysfs_remove_group(&data->bl->dev.kobj,
                        &adp8860_bl_attr_group);
 
-       backlight_device_unregister(data->bl);
-
        return 0;
 }
 
index 90049d7b5c6037adf9edee6992ce606f389f3329..63707205326b8200e0966352aa83e2c65a101ee7 100644 (file)
@@ -238,7 +238,7 @@ static int adp8870_led_setup(struct adp8870_led *led)
 static int adp8870_led_probe(struct i2c_client *client)
 {
        struct adp8870_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct adp8870_bl *data = i2c_get_clientdata(client);
        struct adp8870_led *led, *led_dat;
        struct led_info *cur_led;
@@ -325,7 +325,7 @@ static int adp8870_led_probe(struct i2c_client *client)
 static int adp8870_led_remove(struct i2c_client *client)
 {
        struct adp8870_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct adp8870_bl *data = i2c_get_clientdata(client);
        int i;
 
@@ -848,7 +848,7 @@ static int adp8870_probe(struct i2c_client *client,
        struct backlight_device *bl;
        struct adp8870_bl *data;
        struct adp8870_backlight_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        uint8_t reg_val;
        int ret;
 
@@ -888,8 +888,9 @@ static int adp8870_probe(struct i2c_client *client,
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS;
-       bl = backlight_device_register(dev_driver_string(&client->dev),
-                       &client->dev, data, &adp8870_bl_ops, &props);
+       bl = devm_backlight_device_register(&client->dev,
+                               dev_driver_string(&client->dev),
+                               &client->dev, data, &adp8870_bl_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&client->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -902,7 +903,7 @@ static int adp8870_probe(struct i2c_client *client,
                        &adp8870_bl_attr_group);
                if (ret) {
                        dev_err(&client->dev, "failed to register sysfs\n");
-                       goto out1;
+                       return ret;
                }
        }
 
@@ -925,8 +926,6 @@ out:
        if (data->pdata->en_ambl_sens)
                sysfs_remove_group(&data->bl->dev.kobj,
                        &adp8870_bl_attr_group);
-out1:
-       backlight_device_unregister(bl);
 
        return ret;
 }
@@ -944,8 +943,6 @@ static int adp8870_remove(struct i2c_client *client)
                sysfs_remove_group(&data->bl->dev.kobj,
                        &adp8870_bl_attr_group);
 
-       backlight_device_unregister(data->bl);
-
        return 0;
 }
 
index 319fef6cb4222728489f8a9df2a104655dfa1b13..d8952c4aa689cebdb8520240fb1ebe329d44823c 100644 (file)
@@ -471,14 +471,14 @@ static int ams369fg06_probe(struct spi_device *spi)
        lcd->spi = spi;
        lcd->dev = &spi->dev;
 
-       lcd->lcd_pd = spi->dev.platform_data;
+       lcd->lcd_pd = dev_get_platdata(&spi->dev);
        if (!lcd->lcd_pd) {
                dev_err(&spi->dev, "platform data is NULL\n");
                return -EINVAL;
        }
 
-       ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
-               &ams369fg06_lcd_ops);
+       ld = devm_lcd_device_register(&spi->dev, "ams369fg06", &spi->dev, lcd,
+                                       &ams369fg06_lcd_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -488,12 +488,11 @@ static int ams369fg06_probe(struct spi_device *spi)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
 
-       bd = backlight_device_register("ams369fg06-bl", &spi->dev, lcd,
-               &ams369fg06_backlight_ops, &props);
-       if (IS_ERR(bd)) {
-               ret =  PTR_ERR(bd);
-               goto out_lcd_unregister;
-       }
+       bd = devm_backlight_device_register(&spi->dev, "ams369fg06-bl",
+                                       &spi->dev, lcd,
+                                       &ams369fg06_backlight_ops, &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
 
        bd->props.brightness = DEFAULT_BRIGHTNESS;
        lcd->bd = bd;
@@ -516,10 +515,6 @@ static int ams369fg06_probe(struct spi_device *spi)
        dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n");
 
        return 0;
-
-out_lcd_unregister:
-       lcd_device_unregister(ld);
-       return ret;
 }
 
 static int ams369fg06_remove(struct spi_device *spi)
@@ -527,9 +522,6 @@ static int ams369fg06_remove(struct spi_device *spi)
        struct ams369fg06 *lcd = spi_get_drvdata(spi);
 
        ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
-       backlight_device_unregister(lcd->bd);
-       lcd_device_unregister(lcd->ld);
-
        return 0;
 }
 
index 123887cd76bd7e968919ed5f088063d132afaaaf..bb1fc45b7549e7b0ffd4b49fc1cbce8512e4b0a5 100644 (file)
@@ -240,7 +240,8 @@ static int as3711_bl_register(struct platform_device *pdev,
        /* max tuning I = 31uA for voltage- and 38250uA for current-feedback */
        props.max_brightness = max_brightness;
 
-       bl = backlight_device_register(su->type == AS3711_BL_SU1 ?
+       bl = devm_backlight_device_register(&pdev->dev,
+                                      su->type == AS3711_BL_SU1 ?
                                       "as3711-su1" : "as3711-su2",
                                       &pdev->dev, su,
                                       &as3711_bl_ops, &props);
@@ -432,8 +433,7 @@ static int as3711_backlight_probe(struct platform_device *pdev)
                case AS3711_SU2_LX_SD4:
                        break;
                default:
-                       ret = -EINVAL;
-                       goto esu2;
+                       return -EINVAL;
                }
 
                switch (pdata->su2_feedback) {
@@ -447,8 +447,7 @@ static int as3711_backlight_probe(struct platform_device *pdev)
                        max_brightness = min(pdata->su2_max_uA / 150, 255);
                        break;
                default:
-                       ret = -EINVAL;
-                       goto esu2;
+                       return -EINVAL;
                }
 
                ret = as3711_bl_init_su2(supply);
@@ -457,25 +456,11 @@ static int as3711_backlight_probe(struct platform_device *pdev)
 
                ret = as3711_bl_register(pdev, max_brightness, su);
                if (ret < 0)
-                       goto esu2;
+                       return ret;
        }
 
        platform_set_drvdata(pdev, supply);
 
-       return 0;
-
-esu2:
-       backlight_device_unregister(supply->su1.bl);
-       return ret;
-}
-
-static int as3711_backlight_remove(struct platform_device *pdev)
-{
-       struct as3711_bl_supply *supply = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(supply->su1.bl);
-       backlight_device_unregister(supply->su2.bl);
-
        return 0;
 }
 
@@ -485,7 +470,6 @@ static struct platform_driver as3711_backlight_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = as3711_backlight_probe,
-       .remove         = as3711_backlight_remove,
 };
 
 module_platform_driver(as3711_backlight_driver);
index f7447f7004fb12babc4141d55ee70698806f8a46..261b1a4ec3d8499c782f1f5cf0a15062e2b6545d 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
-#include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/backlight.h>
 #include <linux/atmel_pwm.h>
@@ -27,6 +26,14 @@ struct atmel_pwm_bl {
        int                                     gpio_on;
 };
 
+static void atmel_pwm_bl_set_gpio_on(struct atmel_pwm_bl *pwmbl, int on)
+{
+       if (!gpio_is_valid(pwmbl->gpio_on))
+               return;
+
+       gpio_set_value(pwmbl->gpio_on, on ^ pwmbl->pdata->on_active_low);
+}
+
 static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
 {
        struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
@@ -49,19 +56,13 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
                pwm_duty = pwmbl->pdata->pwm_duty_min;
 
        if (!intensity) {
-               if (pwmbl->gpio_on != -1) {
-                       gpio_set_value(pwmbl->gpio_on,
-                                       0 ^ pwmbl->pdata->on_active_low);
-               }
+               atmel_pwm_bl_set_gpio_on(pwmbl, 0);
                pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
                pwm_channel_disable(&pwmbl->pwmc);
        } else {
                pwm_channel_enable(&pwmbl->pwmc);
                pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
-               if (pwmbl->gpio_on != -1) {
-                       gpio_set_value(pwmbl->gpio_on,
-                                       1 ^ pwmbl->pdata->on_active_low);
-               }
+               atmel_pwm_bl_set_gpio_on(pwmbl, 1);
        }
 
        return 0;
@@ -70,17 +71,16 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
 static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
 {
        struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
-       u8 intensity;
+       u32 cdty;
+       u32 intensity;
 
-       if (pwmbl->pdata->pwm_active_low) {
-               intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) -
-                       pwmbl->pdata->pwm_duty_min;
-       } else {
-               intensity = pwmbl->pdata->pwm_duty_max -
-                       pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
-       }
+       cdty = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
+       if (pwmbl->pdata->pwm_active_low)
+               intensity = cdty - pwmbl->pdata->pwm_duty_min;
+       else
+               intensity = pwmbl->pdata->pwm_duty_max - cdty;
 
-       return intensity;
+       return intensity & 0xffff;
 }
 
 static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
@@ -124,46 +124,40 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
        const struct atmel_pwm_bl_platform_data *pdata;
        struct backlight_device *bldev;
        struct atmel_pwm_bl *pwmbl;
+       unsigned long flags;
        int retval;
 
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata)
+               return -ENODEV;
+
+       if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
+                       pdata->pwm_duty_min > pdata->pwm_duty_max ||
+                       pdata->pwm_frequency == 0)
+               return -EINVAL;
+
        pwmbl = devm_kzalloc(&pdev->dev, sizeof(struct atmel_pwm_bl),
                                GFP_KERNEL);
        if (!pwmbl)
                return -ENOMEM;
 
        pwmbl->pdev = pdev;
-
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               retval = -ENODEV;
-               goto err_free_mem;
-       }
-
-       if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
-                       pdata->pwm_duty_min > pdata->pwm_duty_max ||
-                       pdata->pwm_frequency == 0) {
-               retval = -EINVAL;
-               goto err_free_mem;
-       }
-
        pwmbl->pdata = pdata;
        pwmbl->gpio_on = pdata->gpio_on;
 
        retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
        if (retval)
-               goto err_free_mem;
-
-       if (pwmbl->gpio_on != -1) {
-               retval = devm_gpio_request(&pdev->dev, pwmbl->gpio_on,
-                                       "gpio_atmel_pwm_bl");
-               if (retval) {
-                       pwmbl->gpio_on = -1;
-                       goto err_free_pwm;
-               }
+               return retval;
 
+       if (gpio_is_valid(pwmbl->gpio_on)) {
                /* Turn display off by default. */
-               retval = gpio_direction_output(pwmbl->gpio_on,
-                               0 ^ pdata->on_active_low);
+               if (pdata->on_active_low)
+                       flags = GPIOF_OUT_INIT_HIGH;
+               else
+                       flags = GPIOF_OUT_INIT_LOW;
+
+               retval = devm_gpio_request_one(&pdev->dev, pwmbl->gpio_on,
+                                               flags, "gpio_atmel_pwm_bl");
                if (retval)
                        goto err_free_pwm;
        }
@@ -171,8 +165,9 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
-       bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
-                                         &atmel_pwm_bl_ops, &props);
+       bldev = devm_backlight_device_register(&pdev->dev, "atmel-pwm-bl",
+                                       &pdev->dev, pwmbl, &atmel_pwm_bl_ops,
+                                       &props);
        if (IS_ERR(bldev)) {
                retval = PTR_ERR(bldev);
                goto err_free_pwm;
@@ -188,17 +183,15 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
 
        retval = atmel_pwm_bl_init_pwm(pwmbl);
        if (retval)
-               goto err_free_bl_dev;
+               goto err_free_pwm;
 
        atmel_pwm_bl_set_intensity(bldev);
 
        return 0;
 
-err_free_bl_dev:
-       backlight_device_unregister(bldev);
 err_free_pwm:
        pwm_channel_free(&pwmbl->pwmc);
-err_free_mem:
+
        return retval;
 }
 
@@ -206,11 +199,9 @@ static int atmel_pwm_bl_remove(struct platform_device *pdev)
 {
        struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
 
-       if (pwmbl->gpio_on != -1)
-               gpio_set_value(pwmbl->gpio_on, 0);
+       atmel_pwm_bl_set_gpio_on(pwmbl, 0);
        pwm_channel_disable(&pwmbl->pwmc);
        pwm_channel_free(&pwmbl->pwmc);
-       backlight_device_unregister(pwmbl->bldev);
 
        return 0;
 }
@@ -229,3 +220,4 @@ module_platform_driver(atmel_pwm_bl_driver);
 MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
 MODULE_DESCRIPTION("Atmel PWM backlight driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel-pwm-bl");
index 15e3294b29feb7571558ca3ec8fbe62c71def004..16dd9bc625bdf22951b47f886391469e2647f99b 100644 (file)
@@ -128,7 +128,7 @@ static const struct backlight_ops bd6107_backlight_ops = {
 static int bd6107_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
-       struct bd6107_platform_data *pdata = client->dev.platform_data;
+       struct bd6107_platform_data *pdata = dev_get_platdata(&client->dev);
        struct backlight_device *backlight;
        struct backlight_properties props;
        struct bd6107 *bd;
@@ -166,7 +166,8 @@ static int bd6107_probe(struct i2c_client *client,
        props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
                                   props.max_brightness);
 
-       backlight = backlight_device_register(dev_name(&client->dev),
+       backlight = devm_backlight_device_register(&client->dev,
+                                             dev_name(&client->dev),
                                              &bd->client->dev, bd,
                                              &bd6107_backlight_ops, &props);
        if (IS_ERR(backlight)) {
@@ -186,7 +187,6 @@ static int bd6107_remove(struct i2c_client *client)
 
        backlight->props.brightness = 0;
        backlight_update_status(backlight);
-       backlight_device_unregister(backlight);
 
        return 0;
 }
index c97867a717a7e0f913b01d472c4fbe460df9e9e2..db8db5fa658313b356b0aa42c2c0bd9daa0f08df 100644 (file)
@@ -533,7 +533,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
 static int corgi_lcd_probe(struct spi_device *spi)
 {
        struct backlight_properties props;
-       struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
+       struct corgi_lcd_platform_data *pdata = dev_get_platdata(&spi->dev);
        struct corgi_lcd *lcd;
        int ret = 0;
 
@@ -550,8 +550,8 @@ static int corgi_lcd_probe(struct spi_device *spi)
 
        lcd->spi_dev = spi;
 
-       lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
-                                       lcd, &corgi_lcd_ops);
+       lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "corgi_lcd",
+                                               &spi->dev, lcd, &corgi_lcd_ops);
        if (IS_ERR(lcd->lcd_dev))
                return PTR_ERR(lcd->lcd_dev);
 
@@ -561,18 +561,18 @@ static int corgi_lcd_probe(struct spi_device *spi)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = pdata->max_intensity;
-       lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
-                                               &corgi_bl_ops, &props);
-       if (IS_ERR(lcd->bl_dev)) {
-               ret = PTR_ERR(lcd->bl_dev);
-               goto err_unregister_lcd;
-       }
+       lcd->bl_dev = devm_backlight_device_register(&spi->dev, "corgi_bl",
+                                               &spi->dev, lcd, &corgi_bl_ops,
+                                               &props);
+       if (IS_ERR(lcd->bl_dev))
+               return PTR_ERR(lcd->bl_dev);
+
        lcd->bl_dev->props.brightness = pdata->default_intensity;
        lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
 
        ret = setup_gpio_backlight(lcd, pdata);
        if (ret)
-               goto err_unregister_bl;
+               return ret;
 
        lcd->kick_battery = pdata->kick_battery;
 
@@ -583,12 +583,6 @@ static int corgi_lcd_probe(struct spi_device *spi)
        lcd->limit_mask = pdata->limit_mask;
        the_corgi_lcd = lcd;
        return 0;
-
-err_unregister_bl:
-       backlight_device_unregister(lcd->bl_dev);
-err_unregister_lcd:
-       lcd_device_unregister(lcd->lcd_dev);
-       return ret;
 }
 
 static int corgi_lcd_remove(struct spi_device *spi)
@@ -598,11 +592,7 @@ static int corgi_lcd_remove(struct spi_device *spi)
        lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
        lcd->bl_dev->props.brightness = 0;
        backlight_update_status(lcd->bl_dev);
-       backlight_device_unregister(lcd->bl_dev);
-
        corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
-       lcd_device_unregister(lcd->lcd_dev);
-
        return 0;
 }
 
index 37bae801e23bfa5e9c8085ef6bae47648730ac14..f3fed9ef745f5aca7290677a2f6ae8d866be151e 100644 (file)
@@ -195,16 +195,17 @@ static int cr_backlight_probe(struct platform_device *pdev)
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
-       bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
-                                       &cr_backlight_ops, &props);
+       bdp = devm_backlight_device_register(&pdev->dev, "cr-backlight",
+                                       &pdev->dev, NULL, &cr_backlight_ops,
+                                       &props);
        if (IS_ERR(bdp)) {
                pci_dev_put(lpc_dev);
                return PTR_ERR(bdp);
        }
 
-       ldp = lcd_device_register("cr-lcd", &pdev->dev, NULL, &cr_lcd_ops);
+       ldp = devm_lcd_device_register(&pdev->dev, "cr-lcd", &pdev->dev, NULL,
+                                       &cr_lcd_ops);
        if (IS_ERR(ldp)) {
-               backlight_device_unregister(bdp);
                pci_dev_put(lpc_dev);
                return PTR_ERR(ldp);
        }
@@ -215,8 +216,6 @@ static int cr_backlight_probe(struct platform_device *pdev)
 
        crp = devm_kzalloc(&pdev->dev, sizeof(*crp), GFP_KERNEL);
        if (!crp) {
-               lcd_device_unregister(ldp);
-               backlight_device_unregister(bdp);
                pci_dev_put(lpc_dev);
                return -ENOMEM;
        }
@@ -241,8 +240,6 @@ static int cr_backlight_remove(struct platform_device *pdev)
        crp->cr_backlight_device->props.max_brightness = 0;
        cr_backlight_set_intensity(crp->cr_backlight_device);
        cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN);
-       backlight_device_unregister(crp->cr_backlight_device);
-       lcd_device_unregister(crp->cr_lcd_device);
        pci_dev_put(lpc_dev);
 
        return 0;
index 67cadd30e2735b3e3d42323a631fa61cf1c9b8a3..12c5d840c5909e173fcf34492487b6409f479f67 100644 (file)
@@ -109,7 +109,7 @@ static const struct backlight_ops da903x_backlight_ops = {
 
 static int da903x_backlight_probe(struct platform_device *pdev)
 {
-       struct da9034_backlight_pdata *pdata = pdev->dev.platform_data;
+       struct da9034_backlight_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct da903x_backlight_data *data;
        struct backlight_device *bl;
        struct backlight_properties props;
@@ -144,8 +144,9 @@ static int da903x_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = max_brightness;
-       bl = backlight_device_register(pdev->name, data->da903x_dev, data,
-                                      &da903x_backlight_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, pdev->name,
+                                       data->da903x_dev, data,
+                                       &da903x_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -158,21 +159,12 @@ static int da903x_backlight_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int da903x_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bl);
-       return 0;
-}
-
 static struct platform_driver da903x_backlight_driver = {
        .driver         = {
                .name   = "da903x-backlight",
                .owner  = THIS_MODULE,
        },
        .probe          = da903x_backlight_probe,
-       .remove         = da903x_backlight_remove,
 };
 
 module_platform_driver(da903x_backlight_driver);
index 842da5a3ac4f2fde626b7c23ef7975ab01870eec..20d55becaa7434e76704a7a59771ab413014b09f 100644 (file)
@@ -125,8 +125,9 @@ static int da9052_backlight_probe(struct platform_device *pdev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = DA9052_MAX_BRIGHTNESS;
 
-       bl = backlight_device_register(pdev->name, wleds->da9052->dev, wleds,
-                                      &da9052_backlight_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, pdev->name,
+                                       wleds->da9052->dev, wleds,
+                                       &da9052_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "Failed to register backlight\n");
                return PTR_ERR(bl);
@@ -147,7 +148,6 @@ static int da9052_backlight_remove(struct platform_device *pdev)
        wleds->brightness = 0;
        wleds->state = DA9052_WLEDS_OFF;
        da9052_adjust_wled_brightness(wleds);
-       backlight_device_unregister(bl);
 
        return 0;
 }
index 018368ba4124f0b77f61a4c203b517d20f9b531d..0d1f633c6480190d8dc90d0d122832b4e4c98174 100644 (file)
@@ -92,8 +92,8 @@ static int ep93xxbl_probe(struct platform_device *dev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = EP93XX_MAX_BRIGHT;
-       bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
-                                      &ep93xxbl_ops, &props);
+       bl = devm_backlight_device_register(&dev->dev, dev->name, &dev->dev,
+                                       ep93xxbl, &ep93xxbl_ops, &props);
        if (IS_ERR(bl))
                return PTR_ERR(bl);
 
@@ -106,14 +106,6 @@ static int ep93xxbl_probe(struct platform_device *dev)
        return 0;
 }
 
-static int ep93xxbl_remove(struct platform_device *dev)
-{
-       struct backlight_device *bl = platform_get_drvdata(dev);
-
-       backlight_device_unregister(bl);
-       return 0;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int ep93xxbl_suspend(struct device *dev)
 {
@@ -140,7 +132,6 @@ static struct platform_driver ep93xxbl_driver = {
                .pm     = &ep93xxbl_pm_ops,
        },
        .probe          = ep93xxbl_probe,
-       .remove         = ep93xxbl_remove,
 };
 
 module_platform_driver(ep93xxbl_driver);
index 19e393b41438f21faf8fe91995a2846e0597ba5b..5d8d65200db77b739154c44e394138bc8b332641 100644 (file)
@@ -79,7 +79,7 @@ static const struct backlight_ops genericbl_ops = {
 static int genericbl_probe(struct platform_device *pdev)
 {
        struct backlight_properties props;
-       struct generic_bl_info *machinfo = pdev->dev.platform_data;
+       struct generic_bl_info *machinfo = dev_get_platdata(&pdev->dev);
        const char *name = "generic-bl";
        struct backlight_device *bd;
 
@@ -93,8 +93,8 @@ static int genericbl_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = machinfo->max_intensity;
-       bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
-                                      &props);
+       bd = devm_backlight_device_register(&pdev->dev, name, &pdev->dev,
+                                       NULL, &genericbl_ops, &props);
        if (IS_ERR(bd))
                return PTR_ERR(bd);
 
@@ -118,8 +118,6 @@ static int genericbl_remove(struct platform_device *pdev)
        bd->props.brightness = 0;
        backlight_update_status(bd);
 
-       backlight_device_unregister(bd);
-
        dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n");
        return 0;
 }
index 5fa217f9f4457232e15d23d27ab06db24b68710c..81fb12770c2a259f1ff2a3cc45103b6bc85b5d8a 100644 (file)
@@ -62,7 +62,8 @@ static const struct backlight_ops gpio_backlight_ops = {
 
 static int gpio_backlight_probe(struct platform_device *pdev)
 {
-       struct gpio_backlight_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_backlight_platform_data *pdata =
+               dev_get_platdata(&pdev->dev);
        struct backlight_properties props;
        struct backlight_device *bl;
        struct gpio_backlight *gbl;
@@ -94,8 +95,9 @@ static int gpio_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = 1;
-       bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, gbl,
-                                      &gpio_backlight_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev),
+                                       &pdev->dev, gbl, &gpio_backlight_ops,
+                                       &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -108,21 +110,12 @@ static int gpio_backlight_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int gpio_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bl);
-       return 0;
-}
-
 static struct platform_driver gpio_backlight_driver = {
        .driver         = {
                .name           = "gpio-backlight",
                .owner          = THIS_MODULE,
        },
        .probe          = gpio_backlight_probe,
-       .remove         = gpio_backlight_remove,
 };
 
 module_platform_driver(gpio_backlight_driver);
index c7af8c45ab8a448678181f22c3074cbc7be0e89f..985e854e244b108cc2dce384dc91dbb8f5f8ea73 100644 (file)
@@ -648,7 +648,8 @@ static int hx8357_probe(struct spi_device *spi)
                lcd->use_im_pins = 0;
        }
 
-       lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
+       lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd,
+                                       &hx8357_ops);
        if (IS_ERR(lcdev)) {
                ret = PTR_ERR(lcdev);
                return ret;
@@ -660,32 +661,19 @@ static int hx8357_probe(struct spi_device *spi)
        ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
        if (ret) {
                dev_err(&spi->dev, "Couldn't initialize panel\n");
-               goto init_error;
+               return ret;
        }
 
        dev_info(&spi->dev, "Panel probed\n");
 
        return 0;
-
-init_error:
-       lcd_device_unregister(lcdev);
-       return ret;
-}
-
-static int hx8357_remove(struct spi_device *spi)
-{
-       struct lcd_device *lcdev = spi_get_drvdata(spi);
-
-       lcd_device_unregister(lcdev);
-       return 0;
 }
 
 static struct spi_driver hx8357_driver = {
        .probe  = hx8357_probe,
-       .remove = hx8357_remove,
        .driver = {
                .name = "hx8357",
-               .of_match_table = of_match_ptr(hx8357_dt_ids),
+               .of_match_table = hx8357_dt_ids,
        },
 };
 
index d9f65c2d9b0133635e1a3495e4c192b4e4dac69e..73464e4b4c747e32a32a8b830e1b0c936827e8a5 100644 (file)
@@ -513,8 +513,8 @@ static int ili922x_probe(struct spi_device *spi)
 
        ili->power = FB_BLANK_POWERDOWN;
 
-       lcd = lcd_device_register("ili922xlcd", &spi->dev, ili,
-                                 &ili922x_ops);
+       lcd = devm_lcd_device_register(&spi->dev, "ili922xlcd", &spi->dev, ili,
+                                       &ili922x_ops);
        if (IS_ERR(lcd)) {
                dev_err(&spi->dev, "cannot register LCD\n");
                return PTR_ERR(lcd);
@@ -530,10 +530,7 @@ static int ili922x_probe(struct spi_device *spi)
 
 static int ili922x_remove(struct spi_device *spi)
 {
-       struct ili922x *ili = spi_get_drvdata(spi);
-
        ili922x_poweroff(spi);
-       lcd_device_unregister(ili->ld);
        return 0;
 }
 
index f8be90c5dedcbd772f8d0ad3a6c685da8eb6b9b4..e2b8b40a9bd916db55b56de38ae75fa1032571f1 100644 (file)
@@ -198,7 +198,7 @@ static void ili9320_setup_spi(struct ili9320 *ili,
 int ili9320_probe_spi(struct spi_device *spi,
                                struct ili9320_client *client)
 {
-       struct ili9320_platdata *cfg = spi->dev.platform_data;
+       struct ili9320_platdata *cfg = dev_get_platdata(&spi->dev);
        struct device *dev = &spi->dev;
        struct ili9320 *ili;
        struct lcd_device *lcd;
@@ -235,7 +235,8 @@ int ili9320_probe_spi(struct spi_device *spi,
 
        ili9320_setup_spi(ili, spi);
 
-       lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
+       lcd = devm_lcd_device_register(&spi->dev, "ili9320", dev, ili,
+                                       &ili9320_ops);
        if (IS_ERR(lcd)) {
                dev_err(dev, "failed to register lcd device\n");
                return PTR_ERR(lcd);
@@ -248,24 +249,16 @@ int ili9320_probe_spi(struct spi_device *spi,
        ret = ili9320_power(ili, FB_BLANK_UNBLANK);
        if (ret != 0) {
                dev_err(dev, "failed to set lcd power state\n");
-               goto err_unregister;
+               return ret;
        }
 
        return 0;
-
- err_unregister:
-       lcd_device_unregister(lcd);
-
-       return ret;
 }
 EXPORT_SYMBOL_GPL(ili9320_probe_spi);
 
 int ili9320_remove(struct ili9320 *ili)
 {
        ili9320_power(ili, FB_BLANK_POWERDOWN);
-
-       lcd_device_unregister(ili->lcd);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(ili9320_remove);
index bca6ccc74dfbdf5b69e577819e5f2a9bd028f4cb..7592cc25c963e11638175ff474aaa82c2888a46d 100644 (file)
@@ -141,7 +141,7 @@ static const struct backlight_ops kb3886bl_ops = {
 static int kb3886bl_probe(struct platform_device *pdev)
 {
        struct backlight_properties props;
-       struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data;
+       struct kb3886bl_machinfo *machinfo = dev_get_platdata(&pdev->dev);
 
        bl_machinfo = machinfo;
        if (!machinfo->limit_mask)
@@ -150,10 +150,10 @@ static int kb3886bl_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = machinfo->max_intensity;
-       kb3886_backlight_device = backlight_device_register("kb3886-bl",
-                                                           &pdev->dev, NULL,
-                                                           &kb3886bl_ops,
-                                                           &props);
+       kb3886_backlight_device = devm_backlight_device_register(&pdev->dev,
+                                                       "kb3886-bl", &pdev->dev,
+                                                       NULL, &kb3886bl_ops,
+                                                       &props);
        if (IS_ERR(kb3886_backlight_device))
                return PTR_ERR(kb3886_backlight_device);
 
@@ -166,18 +166,8 @@ static int kb3886bl_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int kb3886bl_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bd = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bd);
-
-       return 0;
-}
-
 static struct platform_driver kb3886bl_driver = {
        .probe          = kb3886bl_probe,
-       .remove         = kb3886bl_remove,
        .driver         = {
                .name   = "kb3886-bl",
                .pm     = &kb3886bl_pm_ops,
index a35a38c709cf03753a717c8be86d14aae982bcc6..923eae2f85f8fbcf6b542c16d9e1f673642274e2 100644 (file)
@@ -48,7 +48,7 @@ static void l4f00242t03_reset(unsigned int gpio)
 
 static void l4f00242t03_lcd_init(struct spi_device *spi)
 {
-       struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
+       struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
        const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
        int ret;
@@ -88,7 +88,7 @@ static void l4f00242t03_lcd_init(struct spi_device *spi)
 
 static void l4f00242t03_lcd_powerdown(struct spi_device *spi)
 {
-       struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
+       struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
 
        dev_dbg(&spi->dev, "Powering down LCD\n");
@@ -171,7 +171,7 @@ static struct lcd_ops l4f_ops = {
 static int l4f00242t03_probe(struct spi_device *spi)
 {
        struct l4f00242t03_priv *priv;
-       struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
+       struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
        int ret;
 
        if (pdata == NULL) {
index 1e0a3093ce5075198f73a17659bc9f6af33621ad..506a6c236039c48daaafbaee938938812129df84 100644 (file)
@@ -702,7 +702,7 @@ static int ld9040_probe(struct spi_device *spi)
        lcd->spi = spi;
        lcd->dev = &spi->dev;
 
-       lcd->lcd_pd = spi->dev.platform_data;
+       lcd->lcd_pd = dev_get_platdata(&spi->dev);
        if (!lcd->lcd_pd) {
                dev_err(&spi->dev, "platform data is NULL.\n");
                return -EINVAL;
@@ -716,7 +716,8 @@ static int ld9040_probe(struct spi_device *spi)
                return ret;
        }
 
-       ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
+       ld = devm_lcd_device_register(&spi->dev, "ld9040", &spi->dev, lcd,
+                                       &ld9040_lcd_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -726,12 +727,10 @@ static int ld9040_probe(struct spi_device *spi)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
 
-       bd = backlight_device_register("ld9040-bl", &spi->dev,
-               lcd, &ld9040_backlight_ops, &props);
-       if (IS_ERR(bd)) {
-               ret = PTR_ERR(bd);
-               goto out_unregister_lcd;
-       }
+       bd = devm_backlight_device_register(&spi->dev, "ld9040-bl", &spi->dev,
+                                       lcd, &ld9040_backlight_ops, &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
 
        bd->props.brightness = MAX_BRIGHTNESS;
        lcd->bd = bd;
@@ -757,11 +756,6 @@ static int ld9040_probe(struct spi_device *spi)
 
        dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
        return 0;
-
-out_unregister_lcd:
-       lcd_device_unregister(lcd->ld);
-
-       return ret;
 }
 
 static int ld9040_remove(struct spi_device *spi)
@@ -769,9 +763,6 @@ static int ld9040_remove(struct spi_device *spi)
        struct ld9040 *lcd = spi_get_drvdata(spi);
 
        ld9040_power(lcd, FB_BLANK_POWERDOWN);
-       backlight_device_unregister(lcd->bd);
-       lcd_device_unregister(lcd->ld);
-
        return 0;
 }
 
index 038d9c86ec031d24ec8282948e06d2a24ef7a8bd..c5e586d973851ef18c6a6b4aa0f83ebe628b1ff2 100644 (file)
@@ -169,7 +169,9 @@ static const unsigned int ld9040_22_50[] = {
 
 struct ld9040_gamma {
        unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
-} gamma_table = {
+};
+
+static struct ld9040_gamma gamma_table = {
        .gamma_22_table[0] = (unsigned int *)&ld9040_22_50,
        .gamma_22_table[1] = (unsigned int *)&ld9040_22_70,
        .gamma_22_table[2] = (unsigned int *)&ld9040_22_80,
index 1d1dbfb789e3aed24628126c748074daef596932..187d1c283c1ddcdb2a1ad06554fffdcdf3e54f4e 100644 (file)
@@ -284,7 +284,7 @@ static int lm3533_bl_probe(struct platform_device *pdev)
        if (!lm3533)
                return -EINVAL;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data\n");
                return -EINVAL;
@@ -313,8 +313,9 @@ static int lm3533_bl_probe(struct platform_device *pdev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = LM3533_BL_MAX_BRIGHTNESS;
        props.brightness = pdata->default_brightness;
-       bd = backlight_device_register(pdata->name, pdev->dev.parent, bl,
-                                               &lm3533_bl_ops, &props);
+       bd = devm_backlight_device_register(&pdev->dev, pdata->name,
+                                       pdev->dev.parent, bl, &lm3533_bl_ops,
+                                       &props);
        if (IS_ERR(bd)) {
                dev_err(&pdev->dev, "failed to register backlight device\n");
                return PTR_ERR(bd);
@@ -328,7 +329,7 @@ static int lm3533_bl_probe(struct platform_device *pdev)
        ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to create sysfs attributes\n");
-               goto err_unregister;
+               return ret;
        }
 
        backlight_update_status(bd);
@@ -345,8 +346,6 @@ static int lm3533_bl_probe(struct platform_device *pdev)
 
 err_sysfs_remove:
        sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
-err_unregister:
-       backlight_device_unregister(bd);
 
        return ret;
 }
@@ -363,7 +362,6 @@ static int lm3533_bl_remove(struct platform_device *pdev)
 
        lm3533_ctrlbank_disable(&bl->cb);
        sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
-       backlight_device_unregister(bd);
 
        return 0;
 }
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
deleted file mode 100644 (file)
index 76a62e9..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
-* Simple driver for Texas Instruments LM3630 Backlight driver chip
-* Copyright (C) 2012 Texas Instruments
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*
-*/
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/backlight.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/platform_data/lm3630_bl.h>
-
-#define REG_CTRL       0x00
-#define REG_CONFIG     0x01
-#define REG_BRT_A      0x03
-#define REG_BRT_B      0x04
-#define REG_INT_STATUS 0x09
-#define REG_INT_EN     0x0A
-#define REG_FAULT      0x0B
-#define REG_PWM_OUTLOW 0x12
-#define REG_PWM_OUTHIGH        0x13
-#define REG_MAX                0x1F
-
-#define INT_DEBOUNCE_MSEC      10
-
-enum lm3630_leds {
-       BLED_ALL = 0,
-       BLED_1,
-       BLED_2
-};
-
-static const char * const bled_name[] = {
-       [BLED_ALL] = "lm3630_bled",     /*Bank1 controls all string */
-       [BLED_1] = "lm3630_bled1",      /*Bank1 controls bled1 */
-       [BLED_2] = "lm3630_bled2",      /*Bank1 or 2 controls bled2 */
-};
-
-struct lm3630_chip_data {
-       struct device *dev;
-       struct delayed_work work;
-       int irq;
-       struct workqueue_struct *irqthread;
-       struct lm3630_platform_data *pdata;
-       struct backlight_device *bled1;
-       struct backlight_device *bled2;
-       struct regmap *regmap;
-};
-
-/* initialize chip */
-static int lm3630_chip_init(struct lm3630_chip_data *pchip)
-{
-       int ret;
-       unsigned int reg_val;
-       struct lm3630_platform_data *pdata = pchip->pdata;
-
-       /*pwm control */
-       reg_val = ((pdata->pwm_active & 0x01) << 2) | (pdata->pwm_ctrl & 0x03);
-       ret = regmap_update_bits(pchip->regmap, REG_CONFIG, 0x07, reg_val);
-       if (ret < 0)
-               goto out;
-
-       /* bank control */
-       reg_val = ((pdata->bank_b_ctrl & 0x01) << 1) |
-                       (pdata->bank_a_ctrl & 0x07);
-       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x07, reg_val);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-       if (ret < 0)
-               goto out;
-
-       /* set initial brightness */
-       if (pdata->bank_a_ctrl != BANK_A_CTRL_DISABLE) {
-               ret = regmap_write(pchip->regmap,
-                                  REG_BRT_A, pdata->init_brt_led1);
-               if (ret < 0)
-                       goto out;
-       }
-
-       if (pdata->bank_b_ctrl != BANK_B_CTRL_DISABLE) {
-               ret = regmap_write(pchip->regmap,
-                                  REG_BRT_B, pdata->init_brt_led2);
-               if (ret < 0)
-                       goto out;
-       }
-       return ret;
-
-out:
-       dev_err(pchip->dev, "i2c failed to access register\n");
-       return ret;
-}
-
-/* interrupt handling */
-static void lm3630_delayed_func(struct work_struct *work)
-{
-       int ret;
-       unsigned int reg_val;
-       struct lm3630_chip_data *pchip;
-
-       pchip = container_of(work, struct lm3630_chip_data, work.work);
-
-       ret = regmap_read(pchip->regmap, REG_INT_STATUS, &reg_val);
-       if (ret < 0) {
-               dev_err(pchip->dev,
-                       "i2c failed to access REG_INT_STATUS Register\n");
-               return;
-       }
-
-       dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", reg_val);
-}
-
-static irqreturn_t lm3630_isr_func(int irq, void *chip)
-{
-       int ret;
-       struct lm3630_chip_data *pchip = chip;
-       unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
-
-       queue_delayed_work(pchip->irqthread, &pchip->work, delay);
-
-       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-       if (ret < 0)
-               goto out;
-
-       return IRQ_HANDLED;
-out:
-       dev_err(pchip->dev, "i2c failed to access register\n");
-       return IRQ_HANDLED;
-}
-
-static int lm3630_intr_config(struct lm3630_chip_data *pchip)
-{
-       INIT_DELAYED_WORK(&pchip->work, lm3630_delayed_func);
-       pchip->irqthread = create_singlethread_workqueue("lm3630-irqthd");
-       if (!pchip->irqthread) {
-               dev_err(pchip->dev, "create irq thread fail...\n");
-               return -1;
-       }
-       if (request_threaded_irq
-           (pchip->irq, NULL, lm3630_isr_func,
-            IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630_irq", pchip)) {
-               dev_err(pchip->dev, "request threaded irq fail..\n");
-               return -1;
-       }
-       return 0;
-}
-
-static bool
-set_intensity(struct backlight_device *bl, struct lm3630_chip_data *pchip)
-{
-       if (!pchip->pdata->pwm_set_intensity)
-               return false;
-       pchip->pdata->pwm_set_intensity(bl->props.brightness - 1,
-                                       pchip->pdata->pwm_period);
-       return true;
-}
-
-/* update and get brightness */
-static int lm3630_bank_a_update_status(struct backlight_device *bl)
-{
-       int ret;
-       struct lm3630_chip_data *pchip = bl_get_data(bl);
-       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
-
-       /* brightness 0 means disable */
-       if (!bl->props.brightness) {
-               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x04, 0x00);
-               if (ret < 0)
-                       goto out;
-               return bl->props.brightness;
-       }
-
-       /* pwm control */
-       if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) {
-               if (!set_intensity(bl, pchip))
-                       dev_err(pchip->dev, "No pwm control func. in plat-data\n");
-       } else {
-
-               /* i2c control */
-               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-               if (ret < 0)
-                       goto out;
-               mdelay(1);
-               ret = regmap_write(pchip->regmap,
-                                  REG_BRT_A, bl->props.brightness - 1);
-               if (ret < 0)
-                       goto out;
-       }
-       return bl->props.brightness;
-out:
-       dev_err(pchip->dev, "i2c failed to access REG_CTRL\n");
-       return bl->props.brightness;
-}
-
-static int lm3630_bank_a_get_brightness(struct backlight_device *bl)
-{
-       unsigned int reg_val;
-       int brightness, ret;
-       struct lm3630_chip_data *pchip = bl_get_data(bl);
-       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
-
-       if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) {
-               ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = reg_val & 0x01;
-               ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = ((brightness << 8) | reg_val) + 1;
-       } else {
-               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-               if (ret < 0)
-                       goto out;
-               mdelay(1);
-               ret = regmap_read(pchip->regmap, REG_BRT_A, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = reg_val + 1;
-       }
-       bl->props.brightness = brightness;
-       return bl->props.brightness;
-out:
-       dev_err(pchip->dev, "i2c failed to access register\n");
-       return 0;
-}
-
-static const struct backlight_ops lm3630_bank_a_ops = {
-       .options = BL_CORE_SUSPENDRESUME,
-       .update_status = lm3630_bank_a_update_status,
-       .get_brightness = lm3630_bank_a_get_brightness,
-};
-
-static int lm3630_bank_b_update_status(struct backlight_device *bl)
-{
-       int ret;
-       struct lm3630_chip_data *pchip = bl_get_data(bl);
-       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
-
-       if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) {
-               if (!set_intensity(bl, pchip))
-                       dev_err(pchip->dev,
-                               "no pwm control func. in plat-data\n");
-       } else {
-               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-               if (ret < 0)
-                       goto out;
-               mdelay(1);
-               ret = regmap_write(pchip->regmap,
-                                  REG_BRT_B, bl->props.brightness - 1);
-       }
-       return bl->props.brightness;
-out:
-       dev_err(pchip->dev, "i2c failed to access register\n");
-       return bl->props.brightness;
-}
-
-static int lm3630_bank_b_get_brightness(struct backlight_device *bl)
-{
-       unsigned int reg_val;
-       int brightness, ret;
-       struct lm3630_chip_data *pchip = bl_get_data(bl);
-       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
-
-       if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) {
-               ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = reg_val & 0x01;
-               ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = ((brightness << 8) | reg_val) + 1;
-       } else {
-               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
-               if (ret < 0)
-                       goto out;
-               mdelay(1);
-               ret = regmap_read(pchip->regmap, REG_BRT_B, &reg_val);
-               if (ret < 0)
-                       goto out;
-               brightness = reg_val + 1;
-       }
-       bl->props.brightness = brightness;
-
-       return bl->props.brightness;
-out:
-       dev_err(pchip->dev, "i2c failed to access register\n");
-       return bl->props.brightness;
-}
-
-static const struct backlight_ops lm3630_bank_b_ops = {
-       .options = BL_CORE_SUSPENDRESUME,
-       .update_status = lm3630_bank_b_update_status,
-       .get_brightness = lm3630_bank_b_get_brightness,
-};
-
-static int lm3630_backlight_register(struct lm3630_chip_data *pchip,
-                                    enum lm3630_leds ledno)
-{
-       const char *name = bled_name[ledno];
-       struct backlight_properties props;
-       struct lm3630_platform_data *pdata = pchip->pdata;
-
-       props.type = BACKLIGHT_RAW;
-       switch (ledno) {
-       case BLED_1:
-       case BLED_ALL:
-               props.brightness = pdata->init_brt_led1;
-               props.max_brightness = pdata->max_brt_led1;
-               pchip->bled1 =
-                   backlight_device_register(name, pchip->dev, pchip,
-                                             &lm3630_bank_a_ops, &props);
-               if (IS_ERR(pchip->bled1))
-                       return PTR_ERR(pchip->bled1);
-               break;
-       case BLED_2:
-               props.brightness = pdata->init_brt_led2;
-               props.max_brightness = pdata->max_brt_led2;
-               pchip->bled2 =
-                   backlight_device_register(name, pchip->dev, pchip,
-                                             &lm3630_bank_b_ops, &props);
-               if (IS_ERR(pchip->bled2))
-                       return PTR_ERR(pchip->bled2);
-               break;
-       }
-       return 0;
-}
-
-static void lm3630_backlight_unregister(struct lm3630_chip_data *pchip)
-{
-       if (pchip->bled1)
-               backlight_device_unregister(pchip->bled1);
-       if (pchip->bled2)
-               backlight_device_unregister(pchip->bled2);
-}
-
-static const struct regmap_config lm3630_regmap = {
-       .reg_bits = 8,
-       .val_bits = 8,
-       .max_register = REG_MAX,
-};
-
-static int lm3630_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
-{
-       struct lm3630_platform_data *pdata = client->dev.platform_data;
-       struct lm3630_chip_data *pchip;
-       int ret;
-
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               dev_err(&client->dev, "fail : i2c functionality check...\n");
-               return -EOPNOTSUPP;
-       }
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "fail : no platform data.\n");
-               return -ENODATA;
-       }
-
-       pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630_chip_data),
-                            GFP_KERNEL);
-       if (!pchip)
-               return -ENOMEM;
-       pchip->pdata = pdata;
-       pchip->dev = &client->dev;
-
-       pchip->regmap = devm_regmap_init_i2c(client, &lm3630_regmap);
-       if (IS_ERR(pchip->regmap)) {
-               ret = PTR_ERR(pchip->regmap);
-               dev_err(&client->dev, "fail : allocate register map: %d\n",
-                       ret);
-               return ret;
-       }
-       i2c_set_clientdata(client, pchip);
-
-       /* chip initialize */
-       ret = lm3630_chip_init(pchip);
-       if (ret < 0) {
-               dev_err(&client->dev, "fail : init chip\n");
-               goto err_chip_init;
-       }
-
-       switch (pdata->bank_a_ctrl) {
-       case BANK_A_CTRL_ALL:
-               ret = lm3630_backlight_register(pchip, BLED_ALL);
-               pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE;
-               break;
-       case BANK_A_CTRL_LED1:
-               ret = lm3630_backlight_register(pchip, BLED_1);
-               break;
-       case BANK_A_CTRL_LED2:
-               ret = lm3630_backlight_register(pchip, BLED_2);
-               pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE;
-               break;
-       default:
-               break;
-       }
-
-       if (ret < 0)
-               goto err_bl_reg;
-
-       if (pdata->bank_b_ctrl && pchip->bled2 == NULL) {
-               ret = lm3630_backlight_register(pchip, BLED_2);
-               if (ret < 0)
-                       goto err_bl_reg;
-       }
-
-       /* interrupt enable  : irq 0 is not allowed for lm3630 */
-       pchip->irq = client->irq;
-       if (pchip->irq)
-               lm3630_intr_config(pchip);
-
-       dev_info(&client->dev, "LM3630 backlight register OK.\n");
-       return 0;
-
-err_bl_reg:
-       dev_err(&client->dev, "fail : backlight register.\n");
-       lm3630_backlight_unregister(pchip);
-err_chip_init:
-       return ret;
-}
-
-static int lm3630_remove(struct i2c_client *client)
-{
-       int ret;
-       struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
-
-       ret = regmap_write(pchip->regmap, REG_BRT_A, 0);
-       if (ret < 0)
-               dev_err(pchip->dev, "i2c failed to access register\n");
-
-       ret = regmap_write(pchip->regmap, REG_BRT_B, 0);
-       if (ret < 0)
-               dev_err(pchip->dev, "i2c failed to access register\n");
-
-       lm3630_backlight_unregister(pchip);
-       if (pchip->irq) {
-               free_irq(pchip->irq, pchip);
-               flush_workqueue(pchip->irqthread);
-               destroy_workqueue(pchip->irqthread);
-       }
-       return 0;
-}
-
-static const struct i2c_device_id lm3630_id[] = {
-       {LM3630_NAME, 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, lm3630_id);
-
-static struct i2c_driver lm3630_i2c_driver = {
-       .driver = {
-                  .name = LM3630_NAME,
-                  },
-       .probe = lm3630_probe,
-       .remove = lm3630_remove,
-       .id_table = lm3630_id,
-};
-
-module_i2c_driver(lm3630_i2c_driver);
-
-MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630");
-MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
-MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
new file mode 100644 (file)
index 0000000..35fe482
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+* Simple driver for Texas Instruments LM3630A Backlight driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/pwm.h>
+#include <linux/platform_data/lm3630a_bl.h>
+
+#define REG_CTRL       0x00
+#define REG_BOOST      0x02
+#define REG_CONFIG     0x01
+#define REG_BRT_A      0x03
+#define REG_BRT_B      0x04
+#define REG_I_A                0x05
+#define REG_I_B                0x06
+#define REG_INT_STATUS 0x09
+#define REG_INT_EN     0x0A
+#define REG_FAULT      0x0B
+#define REG_PWM_OUTLOW 0x12
+#define REG_PWM_OUTHIGH        0x13
+#define REG_MAX                0x1F
+
+#define INT_DEBOUNCE_MSEC      10
+struct lm3630a_chip {
+       struct device *dev;
+       struct delayed_work work;
+
+       int irq;
+       struct workqueue_struct *irqthread;
+       struct lm3630a_platform_data *pdata;
+       struct backlight_device *bleda;
+       struct backlight_device *bledb;
+       struct regmap *regmap;
+       struct pwm_device *pwmd;
+};
+
+/* i2c access */
+static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg)
+{
+       int rval;
+       unsigned int reg_val;
+
+       rval = regmap_read(pchip->regmap, reg, &reg_val);
+       if (rval < 0)
+               return rval;
+       return reg_val & 0xFF;
+}
+
+static int lm3630a_write(struct lm3630a_chip *pchip,
+                        unsigned int reg, unsigned int data)
+{
+       return regmap_write(pchip->regmap, reg, data);
+}
+
+static int lm3630a_update(struct lm3630a_chip *pchip,
+                         unsigned int reg, unsigned int mask,
+                         unsigned int data)
+{
+       return regmap_update_bits(pchip->regmap, reg, mask, data);
+}
+
+/* initialize chip */
+static int lm3630a_chip_init(struct lm3630a_chip *pchip)
+{
+       int rval;
+       struct lm3630a_platform_data *pdata = pchip->pdata;
+
+       usleep_range(1000, 2000);
+       /* set Filter Strength Register */
+       rval = lm3630a_write(pchip, 0x50, 0x03);
+       /* set Cofig. register */
+       rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl);
+       /* set boost control */
+       rval |= lm3630a_write(pchip, REG_BOOST, 0x38);
+       /* set current A */
+       rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F);
+       /* set current B */
+       rval |= lm3630a_write(pchip, REG_I_B, 0x1F);
+       /* set control */
+       rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl);
+       rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl);
+       usleep_range(1000, 2000);
+       /* set brightness A and B */
+       rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt);
+       rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt);
+
+       if (rval < 0)
+               dev_err(pchip->dev, "i2c failed to access register\n");
+       return rval;
+}
+
+/* interrupt handling */
+static void lm3630a_delayed_func(struct work_struct *work)
+{
+       int rval;
+       struct lm3630a_chip *pchip;
+
+       pchip = container_of(work, struct lm3630a_chip, work.work);
+
+       rval = lm3630a_read(pchip, REG_INT_STATUS);
+       if (rval < 0) {
+               dev_err(pchip->dev,
+                       "i2c failed to access REG_INT_STATUS Register\n");
+               return;
+       }
+
+       dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval);
+}
+
+static irqreturn_t lm3630a_isr_func(int irq, void *chip)
+{
+       int rval;
+       struct lm3630a_chip *pchip = chip;
+       unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
+
+       queue_delayed_work(pchip->irqthread, &pchip->work, delay);
+
+       rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
+       if (rval < 0) {
+               dev_err(pchip->dev, "i2c failed to access register\n");
+               return IRQ_NONE;
+       }
+       return IRQ_HANDLED;
+}
+
+static int lm3630a_intr_config(struct lm3630a_chip *pchip)
+{
+       int rval;
+
+       rval = lm3630a_write(pchip, REG_INT_EN, 0x87);
+       if (rval < 0)
+               return rval;
+
+       INIT_DELAYED_WORK(&pchip->work, lm3630a_delayed_func);
+       pchip->irqthread = create_singlethread_workqueue("lm3630a-irqthd");
+       if (!pchip->irqthread) {
+               dev_err(pchip->dev, "create irq thread fail\n");
+               return -ENOMEM;
+       }
+       if (request_threaded_irq
+           (pchip->irq, NULL, lm3630a_isr_func,
+            IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630a_irq", pchip)) {
+               dev_err(pchip->dev, "request threaded irq fail\n");
+               destroy_workqueue(pchip->irqthread);
+               return -ENOMEM;
+       }
+       return rval;
+}
+
+static void lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
+{
+       unsigned int period = pwm_get_period(pchip->pwmd);
+       unsigned int duty = br * period / br_max;
+
+       pwm_config(pchip->pwmd, duty, period);
+       if (duty)
+               pwm_enable(pchip->pwmd);
+       else
+               pwm_disable(pchip->pwmd);
+}
+
+/* update and get brightness */
+static int lm3630a_bank_a_update_status(struct backlight_device *bl)
+{
+       int ret;
+       struct lm3630a_chip *pchip = bl_get_data(bl);
+       enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       /* pwm control */
+       if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
+               lm3630a_pwm_ctrl(pchip, bl->props.brightness,
+                                bl->props.max_brightness);
+               return bl->props.brightness;
+       }
+
+       /* disable sleep */
+       ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
+       if (ret < 0)
+               goto out_i2c_err;
+       usleep_range(1000, 2000);
+       /* minimum brightness is 0x04 */
+       ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
+       if (bl->props.brightness < 0x4)
+               ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
+       else
+               ret |= lm3630a_update(pchip, REG_CTRL,
+                                     LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE);
+       if (ret < 0)
+               goto out_i2c_err;
+       return bl->props.brightness;
+
+out_i2c_err:
+       dev_err(pchip->dev, "i2c failed to access\n");
+       return bl->props.brightness;
+}
+
+static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
+{
+       int brightness, rval;
+       struct lm3630a_chip *pchip = bl_get_data(bl);
+       enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
+               rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
+               if (rval < 0)
+                       goto out_i2c_err;
+               brightness = (rval & 0x01) << 8;
+               rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
+               if (rval < 0)
+                       goto out_i2c_err;
+               brightness |= rval;
+               goto out;
+       }
+
+       /* disable sleep */
+       rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
+       if (rval < 0)
+               goto out_i2c_err;
+       usleep_range(1000, 2000);
+       rval = lm3630a_read(pchip, REG_BRT_A);
+       if (rval < 0)
+               goto out_i2c_err;
+       brightness = rval;
+
+out:
+       bl->props.brightness = brightness;
+       return bl->props.brightness;
+out_i2c_err:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return 0;
+}
+
+static const struct backlight_ops lm3630a_bank_a_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = lm3630a_bank_a_update_status,
+       .get_brightness = lm3630a_bank_a_get_brightness,
+};
+
+/* update and get brightness */
+static int lm3630a_bank_b_update_status(struct backlight_device *bl)
+{
+       int ret;
+       struct lm3630a_chip *pchip = bl_get_data(bl);
+       enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       /* pwm control */
+       if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
+               lm3630a_pwm_ctrl(pchip, bl->props.brightness,
+                                bl->props.max_brightness);
+               return bl->props.brightness;
+       }
+
+       /* disable sleep */
+       ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
+       if (ret < 0)
+               goto out_i2c_err;
+       usleep_range(1000, 2000);
+       /* minimum brightness is 0x04 */
+       ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
+       if (bl->props.brightness < 0x4)
+               ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
+       else
+               ret |= lm3630a_update(pchip, REG_CTRL,
+                                     LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE);
+       if (ret < 0)
+               goto out_i2c_err;
+       return bl->props.brightness;
+
+out_i2c_err:
+       dev_err(pchip->dev, "i2c failed to access REG_CTRL\n");
+       return bl->props.brightness;
+}
+
+static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
+{
+       int brightness, rval;
+       struct lm3630a_chip *pchip = bl_get_data(bl);
+       enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
+               rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
+               if (rval < 0)
+                       goto out_i2c_err;
+               brightness = (rval & 0x01) << 8;
+               rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
+               if (rval < 0)
+                       goto out_i2c_err;
+               brightness |= rval;
+               goto out;
+       }
+
+       /* disable sleep */
+       rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
+       if (rval < 0)
+               goto out_i2c_err;
+       usleep_range(1000, 2000);
+       rval = lm3630a_read(pchip, REG_BRT_B);
+       if (rval < 0)
+               goto out_i2c_err;
+       brightness = rval;
+
+out:
+       bl->props.brightness = brightness;
+       return bl->props.brightness;
+out_i2c_err:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return 0;
+}
+
+static const struct backlight_ops lm3630a_bank_b_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = lm3630a_bank_b_update_status,
+       .get_brightness = lm3630a_bank_b_get_brightness,
+};
+
+static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
+{
+       struct backlight_properties props;
+       struct lm3630a_platform_data *pdata = pchip->pdata;
+
+       props.type = BACKLIGHT_RAW;
+       if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
+               props.brightness = pdata->leda_init_brt;
+               props.max_brightness = pdata->leda_max_brt;
+               pchip->bleda =
+                   devm_backlight_device_register(pchip->dev, "lm3630a_leda",
+                                                  pchip->dev, pchip,
+                                                  &lm3630a_bank_a_ops, &props);
+               if (IS_ERR(pchip->bleda))
+                       return PTR_ERR(pchip->bleda);
+       }
+
+       if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) &&
+           (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
+               props.brightness = pdata->ledb_init_brt;
+               props.max_brightness = pdata->ledb_max_brt;
+               pchip->bledb =
+                   devm_backlight_device_register(pchip->dev, "lm3630a_ledb",
+                                                  pchip->dev, pchip,
+                                                  &lm3630a_bank_b_ops, &props);
+               if (IS_ERR(pchip->bledb))
+                       return PTR_ERR(pchip->bledb);
+       }
+       return 0;
+}
+
+static const struct regmap_config lm3630a_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = REG_MAX,
+};
+
+static int lm3630a_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct lm3630a_chip *pchip;
+       int rval;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "fail : i2c functionality check\n");
+               return -EOPNOTSUPP;
+       }
+
+       pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip),
+                            GFP_KERNEL);
+       if (!pchip)
+               return -ENOMEM;
+       pchip->dev = &client->dev;
+
+       pchip->regmap = devm_regmap_init_i2c(client, &lm3630a_regmap);
+       if (IS_ERR(pchip->regmap)) {
+               rval = PTR_ERR(pchip->regmap);
+               dev_err(&client->dev, "fail : allocate reg. map: %d\n", rval);
+               return rval;
+       }
+
+       i2c_set_clientdata(client, pchip);
+       if (pdata == NULL) {
+               pdata = devm_kzalloc(pchip->dev,
+                                    sizeof(struct lm3630a_platform_data),
+                                    GFP_KERNEL);
+               if (pdata == NULL)
+                       return -ENOMEM;
+               /* default values */
+               pdata->leda_ctrl = LM3630A_LEDA_ENABLE;
+               pdata->ledb_ctrl = LM3630A_LEDB_ENABLE;
+               pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
+               pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
+               pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
+               pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS;
+       }
+       pchip->pdata = pdata;
+
+       /* chip initialize */
+       rval = lm3630a_chip_init(pchip);
+       if (rval < 0) {
+               dev_err(&client->dev, "fail : init chip\n");
+               return rval;
+       }
+       /* backlight register */
+       rval = lm3630a_backlight_register(pchip);
+       if (rval < 0) {
+               dev_err(&client->dev, "fail : backlight register.\n");
+               return rval;
+       }
+       /* pwm */
+       if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) {
+               pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm");
+               if (IS_ERR(pchip->pwmd)) {
+                       dev_err(&client->dev, "fail : get pwm device\n");
+                       return PTR_ERR(pchip->pwmd);
+               }
+       }
+       pchip->pwmd->period = pdata->pwm_period;
+
+       /* interrupt enable  : irq 0 is not allowed */
+       pchip->irq = client->irq;
+       if (pchip->irq) {
+               rval = lm3630a_intr_config(pchip);
+               if (rval < 0)
+                       return rval;
+       }
+       dev_info(&client->dev, "LM3630A backlight register OK.\n");
+       return 0;
+}
+
+static int lm3630a_remove(struct i2c_client *client)
+{
+       int rval;
+       struct lm3630a_chip *pchip = i2c_get_clientdata(client);
+
+       rval = lm3630a_write(pchip, REG_BRT_A, 0);
+       if (rval < 0)
+               dev_err(pchip->dev, "i2c failed to access register\n");
+
+       rval = lm3630a_write(pchip, REG_BRT_B, 0);
+       if (rval < 0)
+               dev_err(pchip->dev, "i2c failed to access register\n");
+
+       if (pchip->irq) {
+               free_irq(pchip->irq, pchip);
+               flush_workqueue(pchip->irqthread);
+               destroy_workqueue(pchip->irqthread);
+       }
+       return 0;
+}
+
+static const struct i2c_device_id lm3630a_id[] = {
+       {LM3630A_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3630a_id);
+
+static struct i2c_driver lm3630a_i2c_driver = {
+       .driver = {
+                  .name = LM3630A_NAME,
+                  },
+       .probe = lm3630a_probe,
+       .remove = lm3630a_remove,
+       .id_table = lm3630a_id,
+};
+
+module_i2c_driver(lm3630a_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630A");
+MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
+MODULE_AUTHOR("LDD MLP <ldd-mlp@list.ti.com>");
+MODULE_LICENSE("GPL v2");
index 053964da8dd3015e2a96ff2d7d9b5083dc6c4653..6fd60adf922ede6393bcd153776bfeebebc998af 100644 (file)
@@ -76,10 +76,13 @@ static int lm3639_chip_init(struct lm3639_chip_data *pchip)
                goto out;
 
        /* output pins config. */
-       if (!pdata->init_brt_led)
-               reg_val = pdata->fled_pins | pdata->bled_pins;
-       else
-               reg_val = pdata->fled_pins | pdata->bled_pins | 0x01;
+       if (!pdata->init_brt_led) {
+               reg_val = pdata->fled_pins;
+               reg_val |= pdata->bled_pins;
+       } else {
+               reg_val = pdata->fled_pins;
+               reg_val |= pdata->bled_pins | 0x01;
+       }
 
        ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val);
        if (ret < 0)
@@ -304,7 +307,7 @@ static int lm3639_probe(struct i2c_client *client,
 {
        int ret;
        struct lm3639_chip_data *pchip;
-       struct lm3639_platform_data *pdata = client->dev.platform_data;
+       struct lm3639_platform_data *pdata = dev_get_platdata(&client->dev);
        struct backlight_properties props;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
index 4eec47261cd38adad7a49565e08cafc66fe5bb3b..de8832504f682422bae9c5bff28743c98ca99d31 100644 (file)
@@ -128,7 +128,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power)
 {
        struct lms283gf05_state *st = lcd_get_data(ld);
        struct spi_device *spi = st->spi;
-       struct lms283gf05_pdata *pdata = spi->dev.platform_data;
+       struct lms283gf05_pdata *pdata = dev_get_platdata(&spi->dev);
 
        if (power <= FB_BLANK_NORMAL) {
                if (pdata)
@@ -153,7 +153,7 @@ static struct lcd_ops lms_ops = {
 static int lms283gf05_probe(struct spi_device *spi)
 {
        struct lms283gf05_state *st;
-       struct lms283gf05_pdata *pdata = spi->dev.platform_data;
+       struct lms283gf05_pdata *pdata = dev_get_platdata(&spi->dev);
        struct lcd_device *ld;
        int ret = 0;
 
@@ -173,7 +173,8 @@ static int lms283gf05_probe(struct spi_device *spi)
                return -ENOMEM;
        }
 
-       ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops);
+       ld = devm_lcd_device_register(&spi->dev, "lms283gf05", &spi->dev, st,
+                                       &lms_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -190,22 +191,12 @@ static int lms283gf05_probe(struct spi_device *spi)
        return 0;
 }
 
-static int lms283gf05_remove(struct spi_device *spi)
-{
-       struct lms283gf05_state *st = spi_get_drvdata(spi);
-
-       lcd_device_unregister(st->ld);
-
-       return 0;
-}
-
 static struct spi_driver lms283gf05_driver = {
        .driver = {
                .name   = "lms283gf05",
                .owner  = THIS_MODULE,
        },
        .probe          = lms283gf05_probe,
-       .remove         = lms283gf05_remove,
 };
 
 module_spi_driver(lms283gf05_driver);
index cf01b9ac813182e0b250799503d40658ed34890e..77258b7b04be288214cba7ee141bf87402c514cf 100644 (file)
@@ -344,14 +344,14 @@ static int lms501kf03_probe(struct spi_device *spi)
        lcd->spi = spi;
        lcd->dev = &spi->dev;
 
-       lcd->lcd_pd = spi->dev.platform_data;
+       lcd->lcd_pd = dev_get_platdata(&spi->dev);
        if (!lcd->lcd_pd) {
                dev_err(&spi->dev, "platform data is NULL\n");
                return -EINVAL;
        }
 
-       ld = lcd_device_register("lms501kf03", &spi->dev, lcd,
-                               &lms501kf03_lcd_ops);
+       ld = devm_lcd_device_register(&spi->dev, "lms501kf03", &spi->dev, lcd,
+                                       &lms501kf03_lcd_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -382,8 +382,6 @@ static int lms501kf03_remove(struct spi_device *spi)
        struct lms501kf03 *lcd = spi_get_drvdata(spi);
 
        lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
-       lcd_device_unregister(lcd->ld);
-
        return 0;
 }
 
index c0b41f13bd4aea01e0156ff11c52e3b585be628d..cae80d555e841fcd22dc844c9bf0d6fe12b87539 100644 (file)
 #define LP8556_EPROM_START             0xA0
 #define LP8556_EPROM_END               0xAF
 
-/* LP8557 Registers */
+/* LP8555/7 Registers */
 #define LP8557_BL_CMD                  0x00
 #define LP8557_BL_MASK                 0x01
 #define LP8557_BL_ON                   0x01
 #define LP8557_BL_OFF                  0x00
 #define LP8557_BRIGHTNESS_CTRL         0x04
 #define LP8557_CONFIG                  0x10
+#define LP8555_EPROM_START             0x10
+#define LP8555_EPROM_END               0x7A
 #define LP8557_EPROM_START             0x10
 #define LP8557_EPROM_END               0x1E
 
@@ -111,6 +113,10 @@ static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
                start = LP8556_EPROM_START;
                end = LP8556_EPROM_END;
                break;
+       case LP8555:
+               start = LP8555_EPROM_START;
+               end = LP8555_EPROM_END;
+               break;
        case LP8557:
                start = LP8557_EPROM_START;
                end = LP8557_EPROM_END;
@@ -165,9 +171,14 @@ static int lp855x_configure(struct lp855x *lp)
        struct lp855x_platform_data *pd = lp->pdata;
 
        switch (lp->chip_id) {
-       case LP8550 ... LP8556:
+       case LP8550:
+       case LP8551:
+       case LP8552:
+       case LP8553:
+       case LP8556:
                lp->cfg = &lp855x_dev_cfg;
                break;
+       case LP8555:
        case LP8557:
                lp->cfg = &lp8557_dev_cfg;
                break;
@@ -289,7 +300,7 @@ static int lp855x_backlight_register(struct lp855x *lp)
 
        props.brightness = pdata->initial_brightness;
 
-       bl = backlight_device_register(name, lp->dev, lp,
+       bl = devm_backlight_device_register(lp->dev, name, lp->dev, lp,
                                       &lp855x_bl_ops, &props);
        if (IS_ERR(bl))
                return PTR_ERR(bl);
@@ -299,12 +310,6 @@ static int lp855x_backlight_register(struct lp855x *lp)
        return 0;
 }
 
-static void lp855x_backlight_unregister(struct lp855x *lp)
-{
-       if (lp->bl)
-               backlight_device_unregister(lp->bl);
-}
-
 static ssize_t lp855x_get_chip_id(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -394,7 +399,7 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
        struct lp855x *lp;
-       struct lp855x_platform_data *pdata = cl->dev.platform_data;
+       struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
        struct device_node *node = cl->dev.of_node;
        int ret;
 
@@ -403,7 +408,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
                if (ret < 0)
                        return ret;
 
-               pdata = cl->dev.platform_data;
+               pdata = dev_get_platdata(&cl->dev);
        }
 
        if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
@@ -428,29 +433,24 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        ret = lp855x_configure(lp);
        if (ret) {
                dev_err(lp->dev, "device config err: %d", ret);
-               goto err_dev;
+               return ret;
        }
 
        ret = lp855x_backlight_register(lp);
        if (ret) {
                dev_err(lp->dev,
                        "failed to register backlight. err: %d\n", ret);
-               goto err_dev;
+               return ret;
        }
 
        ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group);
        if (ret) {
                dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
-               goto err_sysfs;
+               return ret;
        }
 
        backlight_update_status(lp->bl);
        return 0;
-
-err_sysfs:
-       lp855x_backlight_unregister(lp);
-err_dev:
-       return ret;
 }
 
 static int lp855x_remove(struct i2c_client *cl)
@@ -460,7 +460,6 @@ static int lp855x_remove(struct i2c_client *cl)
        lp->bl->props.brightness = 0;
        backlight_update_status(lp->bl);
        sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
-       lp855x_backlight_unregister(lp);
 
        return 0;
 }
@@ -470,6 +469,7 @@ static const struct of_device_id lp855x_dt_ids[] = {
        { .compatible = "ti,lp8551", },
        { .compatible = "ti,lp8552", },
        { .compatible = "ti,lp8553", },
+       { .compatible = "ti,lp8555", },
        { .compatible = "ti,lp8556", },
        { .compatible = "ti,lp8557", },
        { }
@@ -481,6 +481,7 @@ static const struct i2c_device_id lp855x_ids[] = {
        {"lp8551", LP8551},
        {"lp8552", LP8552},
        {"lp8553", LP8553},
+       {"lp8555", LP8555},
        {"lp8556", LP8556},
        {"lp8557", LP8557},
        { }
index 980855ec9bb10c2c8421f59a48a65bd9a82af60f..e49905d495dcd66102df9113f068128aee4f8a7b 100644 (file)
@@ -52,7 +52,7 @@ struct lp8788_bl {
        struct pwm_device *pwm;
 };
 
-struct lp8788_bl_config default_bl_config = {
+static struct lp8788_bl_config default_bl_config = {
        .bl_mode    = LP8788_BL_REGISTER_ONLY,
        .dim_mode   = LP8788_DIM_EXPONENTIAL,
        .full_scale = LP8788_FULLSCALE_1900uA,
index ed1b3926813162d19644a8957c4c36a19a574549..383f550e165ec0070809bf56799cdb3e0a52ac44 100644 (file)
@@ -242,7 +242,8 @@ static int ltv350qv_probe(struct spi_device *spi)
        if (!lcd->buffer)
                return -ENOMEM;
 
-       ld = lcd_device_register("ltv350qv", &spi->dev, lcd, &ltv_ops);
+       ld = devm_lcd_device_register(&spi->dev, "ltv350qv", &spi->dev, lcd,
+                                       &ltv_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -250,15 +251,11 @@ static int ltv350qv_probe(struct spi_device *spi)
 
        ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
        if (ret)
-               goto out_unregister;
+               return ret;
 
        spi_set_drvdata(spi, lcd);
 
        return 0;
-
-out_unregister:
-       lcd_device_unregister(ld);
-       return ret;
 }
 
 static int ltv350qv_remove(struct spi_device *spi)
@@ -266,8 +263,6 @@ static int ltv350qv_remove(struct spi_device *spi)
        struct ltv350qv *lcd = spi_get_drvdata(spi);
 
        ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
-       lcd_device_unregister(lcd->ld);
-
        return 0;
 }
 
index 498fd73d59b9d801f67942e2be5ca4d572bf487c..1802b2d1357d6cbff959d0deab949fc0d9e08746 100644 (file)
@@ -93,7 +93,7 @@ static const struct backlight_ops lv5207lp_backlight_ops = {
 static int lv5207lp_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
-       struct lv5207lp_platform_data *pdata = client->dev.platform_data;
+       struct lv5207lp_platform_data *pdata = dev_get_platdata(&client->dev);
        struct backlight_device *backlight;
        struct backlight_properties props;
        struct lv5207lp *lv;
@@ -124,9 +124,9 @@ static int lv5207lp_probe(struct i2c_client *client,
        props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
                                   props.max_brightness);
 
-       backlight = backlight_device_register(dev_name(&client->dev),
-                                             &lv->client->dev, lv,
-                                             &lv5207lp_backlight_ops, &props);
+       backlight = devm_backlight_device_register(&client->dev,
+                               dev_name(&client->dev), &lv->client->dev,
+                               lv, &lv5207lp_backlight_ops, &props);
        if (IS_ERR(backlight)) {
                dev_err(&client->dev, "failed to register backlight\n");
                return PTR_ERR(backlight);
@@ -144,7 +144,6 @@ static int lv5207lp_remove(struct i2c_client *client)
 
        backlight->props.brightness = 0;
        backlight_update_status(backlight);
-       backlight_device_unregister(backlight);
 
        return 0;
 }
index 886e797f75f9e7b0c6571f2f8ba0ec0b561f0d83..66fa08c920d25c61e492e8e639f5eea722835a36 100644 (file)
@@ -163,7 +163,8 @@ static int max8925_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
-       bl = backlight_device_register("max8925-backlight", &pdev->dev, data,
+       bl = devm_backlight_device_register(&pdev->dev, "max8925-backlight",
+                                       &pdev->dev, data,
                                        &max8925_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
@@ -188,20 +189,9 @@ static int max8925_backlight_probe(struct platform_device *pdev)
        }
        ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value);
        if (ret < 0)
-               goto out_brt;
+               return ret;
        backlight_update_status(bl);
        return 0;
-out_brt:
-       backlight_device_unregister(bl);
-       return ret;
-}
-
-static int max8925_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bl);
-       return 0;
 }
 
 static struct platform_driver max8925_backlight_driver = {
@@ -210,7 +200,6 @@ static struct platform_driver max8925_backlight_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = max8925_backlight_probe,
-       .remove         = max8925_backlight_remove,
 };
 
 module_platform_driver(max8925_backlight_driver);
index 812e22e35cabb4c48a9e2a9ff5360a2116c41a61..ac11a4650c19ea92fcfe26d6720fda8d64913fbf 100644 (file)
@@ -133,7 +133,7 @@ static int omapbl_probe(struct platform_device *pdev)
        struct backlight_properties props;
        struct backlight_device *dev;
        struct omap_backlight *bl;
-       struct omap_backlight_config *pdata = pdev->dev.platform_data;
+       struct omap_backlight_config *pdata = dev_get_platdata(&pdev->dev);
 
        if (!pdata)
                return -ENXIO;
index 633b0a22fd64446db61d63755069963e75f1aff0..2098c5d6efb9de7dc03c62026877b80578fdfd89 100644 (file)
@@ -120,8 +120,8 @@ static int pandora_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(props));
        props.max_brightness = MAX_USER_VALUE;
        props.type = BACKLIGHT_RAW;
-       bl = backlight_device_register(pdev->name, &pdev->dev,
-                       NULL, &pandora_backlight_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, pdev->name, &pdev->dev,
+                                       NULL, &pandora_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -145,20 +145,12 @@ static int pandora_backlight_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pandora_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-       backlight_device_unregister(bl);
-       return 0;
-}
-
 static struct platform_driver pandora_backlight_driver = {
        .driver         = {
                .name   = "pandora-backlight",
                .owner  = THIS_MODULE,
        },
        .probe          = pandora_backlight_probe,
-       .remove         = pandora_backlight_remove,
 };
 
 module_platform_driver(pandora_backlight_driver);
index 6ed76be18f1943e55fd7ad405c490a8749833358..b95d3b0aaffee03dc5f5f0380d91b456ea5293cb 100644 (file)
@@ -103,7 +103,7 @@ static int pcf50633_bl_probe(struct platform_device *pdev)
 {
        struct pcf50633_bl *pcf_bl;
        struct device *parent = pdev->dev.parent;
-       struct pcf50633_platform_data *pcf50633_data = parent->platform_data;
+       struct pcf50633_platform_data *pcf50633_data = dev_get_platdata(parent);
        struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data;
        struct backlight_properties bl_props;
 
@@ -126,7 +126,8 @@ static int pcf50633_bl_probe(struct platform_device *pdev)
 
        pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent);
 
-       pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl,
+       pcf_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name,
+                                               &pdev->dev, pcf_bl,
                                                &pcf50633_bl_ops, &bl_props);
 
        if (IS_ERR(pcf_bl->bl))
@@ -147,18 +148,8 @@ static int pcf50633_bl_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pcf50633_bl_remove(struct platform_device *pdev)
-{
-       struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(pcf_bl->bl);
-
-       return 0;
-}
-
 static struct platform_driver pcf50633_bl_driver = {
        .probe =        pcf50633_bl_probe,
-       .remove =       pcf50633_bl_remove,
        .driver = {
                .name = "pcf50633-backlight",
        },
index 05683670670895aeaf061979c776ff3150c1b370..d01884d4f1bff982033e2b4e68219c37290e7cce 100644 (file)
@@ -80,7 +80,7 @@ static int platform_lcd_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int err;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(dev, "no platform data supplied\n");
                return -EINVAL;
@@ -101,29 +101,16 @@ static int platform_lcd_probe(struct platform_device *pdev)
 
        plcd->us = dev;
        plcd->pdata = pdata;
-       plcd->lcd = lcd_device_register(dev_name(dev), dev,
-                                       plcd, &platform_lcd_ops);
+       plcd->lcd = devm_lcd_device_register(&pdev->dev, dev_name(dev), dev,
+                                               plcd, &platform_lcd_ops);
        if (IS_ERR(plcd->lcd)) {
                dev_err(dev, "cannot register lcd device\n");
-               err = PTR_ERR(plcd->lcd);
-               goto err;
+               return PTR_ERR(plcd->lcd);
        }
 
        platform_set_drvdata(pdev, plcd);
        platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL);
 
-       return 0;
-
- err:
-       return err;
-}
-
-static int platform_lcd_remove(struct platform_device *pdev)
-{
-       struct platform_lcd *plcd = platform_get_drvdata(pdev);
-
-       lcd_device_unregister(plcd->lcd);
-
        return 0;
 }
 
@@ -168,7 +155,6 @@ static struct platform_driver platform_lcd_driver = {
                .of_match_table = of_match_ptr(platform_lcd_of_match),
        },
        .probe          = platform_lcd_probe,
-       .remove         = platform_lcd_remove,
 };
 
 module_platform_driver(platform_lcd_driver);
index 1fea627394d7c419107506d2b29d4cd052ea3b59..36db5d98dd2f5e900d9dafe3bd6e0e10b30e082e 100644 (file)
@@ -163,7 +163,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
 static int pwm_backlight_probe(struct platform_device *pdev)
 {
-       struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
+       struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
        struct platform_pwm_backlight_data defdata;
        struct backlight_properties props;
        struct backlight_device *bl;
index b37bb1854bf45b9cd56d70a6135e9d44422695ac..510a1bcf76f11d95a5d936099846abc5c4c49bdf 100644 (file)
@@ -735,13 +735,14 @@ static int s6e63m0_probe(struct spi_device *spi)
        lcd->spi = spi;
        lcd->dev = &spi->dev;
 
-       lcd->lcd_pd = spi->dev.platform_data;
+       lcd->lcd_pd = dev_get_platdata(&spi->dev);
        if (!lcd->lcd_pd) {
                dev_err(&spi->dev, "platform data is NULL.\n");
                return -EINVAL;
        }
 
-       ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
+       ld = devm_lcd_device_register(&spi->dev, "s6e63m0", &spi->dev, lcd,
+                               &s6e63m0_lcd_ops);
        if (IS_ERR(ld))
                return PTR_ERR(ld);
 
@@ -751,12 +752,11 @@ static int s6e63m0_probe(struct spi_device *spi)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
 
-       bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
-               &s6e63m0_backlight_ops, &props);
-       if (IS_ERR(bd)) {
-               ret =  PTR_ERR(bd);
-               goto out_lcd_unregister;
-       }
+       bd = devm_backlight_device_register(&spi->dev, "s6e63m0bl-bl",
+                                       &spi->dev, lcd, &s6e63m0_backlight_ops,
+                                       &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
 
        bd->props.brightness = MAX_BRIGHTNESS;
        lcd->bd = bd;
@@ -798,10 +798,6 @@ static int s6e63m0_probe(struct spi_device *spi)
        dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n");
 
        return 0;
-
-out_lcd_unregister:
-       lcd_device_unregister(ld);
-       return ret;
 }
 
 static int s6e63m0_remove(struct spi_device *spi)
@@ -811,8 +807,6 @@ static int s6e63m0_remove(struct spi_device *spi)
        s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
        device_remove_file(&spi->dev, &dev_attr_gamma_table);
        device_remove_file(&spi->dev, &dev_attr_gamma_mode);
-       backlight_device_unregister(lcd->bd);
-       lcd_device_unregister(lcd->ld);
 
        return 0;
 }
index 18cdf466d50a5710ea73e0ae5d7ce34a5d188d83..908016fc5829ff3ef0667f5be62c51999d30106e 100644 (file)
@@ -338,7 +338,7 @@ static int tdo24m_probe(struct spi_device *spi)
        enum tdo24m_model model;
        int err;
 
-       pdata = spi->dev.platform_data;
+       pdata = dev_get_platdata(&spi->dev);
        if (pdata)
                model = pdata->model;
        else
@@ -385,21 +385,17 @@ static int tdo24m_probe(struct spi_device *spi)
                return -EINVAL;
        }
 
-       lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
-                                       lcd, &tdo24m_ops);
+       lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "tdo24m", &spi->dev,
+                                               lcd, &tdo24m_ops);
        if (IS_ERR(lcd->lcd_dev))
                return PTR_ERR(lcd->lcd_dev);
 
        spi_set_drvdata(spi, lcd);
        err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
        if (err)
-               goto out_unregister;
+               return err;
 
        return 0;
-
-out_unregister:
-       lcd_device_unregister(lcd->lcd_dev);
-       return err;
 }
 
 static int tdo24m_remove(struct spi_device *spi)
@@ -407,8 +403,6 @@ static int tdo24m_remove(struct spi_device *spi)
        struct tdo24m *lcd = spi_get_drvdata(spi);
 
        tdo24m_power(lcd, FB_BLANK_POWERDOWN);
-       lcd_device_unregister(lcd->lcd_dev);
-
        return 0;
 }
 
index 9df66ac68b344e46f8b5a9b0de8b532a3c9acb9a..b8db9338cacddcdadc9cd7d2c08364a9604c4bff 100644 (file)
@@ -38,7 +38,7 @@ struct tosa_bl_data {
 
 static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness)
 {
-       struct spi_device *spi = data->i2c->dev.platform_data;
+       struct spi_device *spi = dev_get_platdata(&data->i2c->dev);
 
        i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj);
 
index 05782312aeb34dbadeca7545ba24c52edcb02f5c..cbba37e6836e1b07aedf8e35aebfe8e1440cc23b 100644 (file)
@@ -287,12 +287,11 @@ static int tps65217_bl_probe(struct platform_device *pdev)
                if (IS_ERR(pdata))
                        return PTR_ERR(pdata);
        } else {
-               if (!pdev->dev.platform_data) {
+               pdata = dev_get_platdata(&pdev->dev);
+               if (!pdata) {
                        dev_err(&pdev->dev, "no platform data provided\n");
                        return -EINVAL;
                }
-
-               pdata = pdev->dev.platform_data;
        }
 
        tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
@@ -314,7 +313,7 @@ static int tps65217_bl_probe(struct platform_device *pdev)
        bl_props.type = BACKLIGHT_RAW;
        bl_props.max_brightness = 100;
 
-       tps65217_bl->bl = backlight_device_register(pdev->name,
+       tps65217_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name,
                                                tps65217_bl->dev, tps65217_bl,
                                                &tps65217_bl_ops, &bl_props);
        if (IS_ERR(tps65217_bl->bl)) {
@@ -330,18 +329,8 @@ static int tps65217_bl_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int tps65217_bl_remove(struct platform_device *pdev)
-{
-       struct tps65217_bl *tps65217_bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(tps65217_bl->bl);
-
-       return 0;
-}
-
 static struct platform_driver tps65217_bl_driver = {
        .probe          = tps65217_bl_probe,
-       .remove         = tps65217_bl_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "tps65217-bl",
index 9e5517a3a52baeea6546e0d24dc4a8ca2e5ef732..8b9455e9306930027b4fa20454b2ac837d8b4ff9 100644 (file)
@@ -123,7 +123,7 @@ static const struct backlight_ops wm831x_backlight_ops = {
 static int wm831x_backlight_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-       struct wm831x_pdata *wm831x_pdata;
+       struct wm831x_pdata *wm831x_pdata = dev_get_platdata(pdev->dev.parent);
        struct wm831x_backlight_pdata *pdata;
        struct wm831x_backlight_data *data;
        struct backlight_device *bl;
@@ -131,12 +131,10 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
        int ret, i, max_isel, isink_reg, dcdc_cfg;
 
        /* We need platform data */
-       if (pdev->dev.parent->platform_data) {
-               wm831x_pdata = pdev->dev.parent->platform_data;
+       if (wm831x_pdata)
                pdata = wm831x_pdata->backlight;
-       } else {
+       else
                pdata = NULL;
-       }
 
        if (!pdata) {
                dev_err(&pdev->dev, "No platform data supplied\n");
@@ -197,8 +195,8 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = max_isel;
-       bl = backlight_device_register("wm831x", &pdev->dev, data,
-                                      &wm831x_backlight_ops, &props);
+       bl = devm_backlight_device_register(&pdev->dev, "wm831x", &pdev->dev,
+                                       data, &wm831x_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                return PTR_ERR(bl);
@@ -216,21 +214,12 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int wm831x_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_device_unregister(bl);
-       return 0;
-}
-
 static struct platform_driver wm831x_backlight_driver = {
        .driver         = {
                .name   = "wm831x-backlight",
                .owner  = THIS_MODULE,
        },
        .probe          = wm831x_backlight_probe,
-       .remove         = wm831x_backlight_remove,
 };
 
 module_platform_driver(wm831x_backlight_driver);
index 41613f92a723448c1b4091a7e357fc05b2af9638..02df3b1381d2f639c2ff5d756adad8915198fde7 100644 (file)
@@ -255,17 +255,17 @@ static int ds1wm_find_divisor(int gclk)
 static void ds1wm_up(struct ds1wm_data *ds1wm_data)
 {
        int divisor;
-       struct ds1wm_driver_data *plat = ds1wm_data->pdev->dev.platform_data;
+       struct device *dev = &ds1wm_data->pdev->dev;
+       struct ds1wm_driver_data *plat = dev_get_platdata(dev);
 
        if (ds1wm_data->cell->enable)
                ds1wm_data->cell->enable(ds1wm_data->pdev);
 
        divisor = ds1wm_find_divisor(plat->clock_rate);
-       dev_dbg(&ds1wm_data->pdev->dev,
-               "found divisor 0x%x for clock %d\n", divisor, plat->clock_rate);
+       dev_dbg(dev, "found divisor 0x%x for clock %d\n",
+               divisor, plat->clock_rate);
        if (divisor == 0) {
-               dev_err(&ds1wm_data->pdev->dev,
-                       "no suitable divisor for %dHz clock\n",
+               dev_err(dev, "no suitable divisor for %dHz clock\n",
                        plat->clock_rate);
                return;
        }
@@ -481,7 +481,7 @@ static int ds1wm_probe(struct platform_device *pdev)
        ds1wm_data->cell = mfd_get_cell(pdev);
        if (!ds1wm_data->cell)
                return -ENODEV;
-       plat = pdev->dev.platform_data;
+       plat = dev_get_platdata(&pdev->dev);
        if (!plat)
                return -ENODEV;
 
index fa932c2f7d97276b66199eda06b6edb6565208bb..66efa96c460354b6fb8087634be49e3a25643fd0 100644 (file)
@@ -709,7 +709,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
        sl->owner = THIS_MODULE;
        sl->master = dev;
-       set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+       set_bit(W1_SLAVE_ACTIVE, &sl->flags);
 
        memset(&msg, 0, sizeof(msg));
        memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
@@ -866,7 +866,7 @@ void w1_slave_found(struct w1_master *dev, u64 rn)
 
        sl = w1_slave_search_device(dev, tmp);
        if (sl) {
-               set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+               set_bit(W1_SLAVE_ACTIVE, &sl->flags);
        } else {
                if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7))
                        w1_attach_slave_device(dev, tmp);
@@ -984,14 +984,14 @@ void w1_search_process_cb(struct w1_master *dev, u8 search_type,
        struct w1_slave *sl, *sln;
 
        list_for_each_entry(sl, &dev->slist, w1_slave_entry)
-               clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+               clear_bit(W1_SLAVE_ACTIVE, &sl->flags);
 
        w1_search_devices(dev, search_type, cb);
 
        list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-               if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl)
+               if (!test_bit(W1_SLAVE_ACTIVE, &sl->flags) && !--sl->ttl)
                        w1_slave_detach(sl);
-               else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+               else if (test_bit(W1_SLAVE_ACTIVE, &sl->flags))
                        sl->ttl = dev->slave_ttl;
        }
 
index 45908e56c2f834180ca0b166e44bd9fca50a5e2d..ca8081a101d64ac34fadbc872aeaf3e0898c4fc8 100644 (file)
@@ -67,8 +67,8 @@ struct w1_slave
        struct w1_reg_num       reg_num;
        atomic_t                refcnt;
        u8                      rom[9];
-       u32                     flags;
        int                     ttl;
+       unsigned long           flags;
 
        struct w1_master        *master;
        struct w1_family        *family;
index cd06466f365ea53619afb313cd87befdc5221db5..11b29d491b7c5856fa68937eccf9529b9c1b0523 100644 (file)
@@ -1,5 +1,5 @@
 config CRAMFS
-       tristate "Compressed ROM file system support (cramfs)"
+       tristate "Compressed ROM file system support (cramfs) (OBSOLETE)"
        depends on BLOCK
        select ZLIB_INFLATE
        help
@@ -16,4 +16,7 @@ config CRAMFS
          cramfs.  Note that the root file system (the one containing the
          directory /) cannot be compiled as a module.
 
+         This filesystem is obsoleted by SquashFS, which is much better
+         in terms of performance and features.
+
          If unsure, say N.
index c7c83ff0f752ce6a86d6e42a420e34ed996ae8ca..9c0444cccbe108b245338a0d40a5d702fbe45407 100644 (file)
@@ -566,8 +566,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
        mutex_lock(&parent->d_inode->i_mutex);
 
        if (child != dentry) {
-               next = list_entry(child->d_u.d_child.next, struct dentry,
-                                       d_u.d_child);
+               next = list_next_entry(child, d_u.d_child);
                goto up;
        }
 
index 073d30b9d1acdc735eee53cdc26330df46294165..a726b9f29cb71735eb99ada9367f4348da45eb3d 100644 (file)
@@ -498,6 +498,7 @@ static void devpts_kill_sb(struct super_block *sb)
 {
        struct pts_fs_info *fsi = DEVPTS_SB(sb);
 
+       ida_destroy(&fsi->allocated_ptys);
        kfree(fsi);
        kill_litter_super(sb);
 }
index 983e3960abffc4a36f901092f5aae5cc55d58e30..79b65c3b9e876f1087ccbcf7908a47c18efbbad9 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/compat.h>
+#include <linux/rculist.h>
 
 /*
  * LOCKING:
@@ -133,8 +134,12 @@ struct nested_calls {
  * of these on a server and we do not want this to take another cache line.
  */
 struct epitem {
-       /* RB tree node used to link this structure to the eventpoll RB tree */
-       struct rb_node rbn;
+       union {
+               /* RB tree node links this structure to the eventpoll RB tree */
+               struct rb_node rbn;
+               /* Used to free the struct epitem */
+               struct rcu_head rcu;
+       };
 
        /* List header used to link this structure to the eventpoll ready list */
        struct list_head rdllink;
@@ -580,14 +585,14 @@ static inline void ep_pm_stay_awake_rcu(struct epitem *epi)
  * @sproc: Pointer to the scan callback.
  * @priv: Private opaque data passed to the @sproc callback.
  * @depth: The current depth of recursive f_op->poll calls.
+ * @ep_locked: caller already holds ep->mtx
  *
  * Returns: The same integer error code returned by the @sproc callback.
  */
 static int ep_scan_ready_list(struct eventpoll *ep,
                              int (*sproc)(struct eventpoll *,
                                           struct list_head *, void *),
-                             void *priv,
-                             int depth)
+                             void *priv, int depth, bool ep_locked)
 {
        int error, pwake = 0;
        unsigned long flags;
@@ -598,7 +603,9 @@ static int ep_scan_ready_list(struct eventpoll *ep,
         * We need to lock this because we could be hit by
         * eventpoll_release_file() and epoll_ctl().
         */
-       mutex_lock_nested(&ep->mtx, depth);
+
+       if (!ep_locked)
+               mutex_lock_nested(&ep->mtx, depth);
 
        /*
         * Steal the ready list, and re-init the original one to the
@@ -662,7 +669,8 @@ static int ep_scan_ready_list(struct eventpoll *ep,
        }
        spin_unlock_irqrestore(&ep->lock, flags);
 
-       mutex_unlock(&ep->mtx);
+       if (!ep_locked)
+               mutex_unlock(&ep->mtx);
 
        /* We have to call this outside the lock */
        if (pwake)
@@ -671,6 +679,12 @@ static int ep_scan_ready_list(struct eventpoll *ep,
        return error;
 }
 
+static void epi_rcu_free(struct rcu_head *head)
+{
+       struct epitem *epi = container_of(head, struct epitem, rcu);
+       kmem_cache_free(epi_cache, epi);
+}
+
 /*
  * Removes a "struct epitem" from the eventpoll RB tree and deallocates
  * all the associated resources. Must be called with "mtx" held.
@@ -692,8 +706,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 
        /* Remove the current item from the list of epoll hooks */
        spin_lock(&file->f_lock);
-       if (ep_is_linked(&epi->fllink))
-               list_del_init(&epi->fllink);
+       list_del_rcu(&epi->fllink);
        spin_unlock(&file->f_lock);
 
        rb_erase(&epi->rbn, &ep->rbr);
@@ -704,9 +717,14 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        spin_unlock_irqrestore(&ep->lock, flags);
 
        wakeup_source_unregister(ep_wakeup_source(epi));
-
-       /* At this point it is safe to free the eventpoll item */
-       kmem_cache_free(epi_cache, epi);
+       /*
+        * At this point it is safe to free the eventpoll item. Use the union
+        * field epi->rcu, since we are trying to minimize the size of
+        * 'struct epitem'. The 'rbn' field is no longer in use. Protected by
+        * ep->mtx. The rcu read side, reverse_path_check_proc(), does not make
+        * use of the rbn field.
+        */
+       call_rcu(&epi->rcu, epi_rcu_free);
 
        atomic_long_dec(&ep->user->epoll_watches);
 
@@ -807,15 +825,34 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
        return 0;
 }
 
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
+                                poll_table *pt);
+
+struct readyevents_arg {
+       struct eventpoll *ep;
+       bool locked;
+};
+
 static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests)
 {
-       return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1);
+       struct readyevents_arg *arg = priv;
+
+       return ep_scan_ready_list(arg->ep, ep_read_events_proc, NULL,
+                                 call_nests + 1, arg->locked);
 }
 
 static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
 {
        int pollflags;
        struct eventpoll *ep = file->private_data;
+       struct readyevents_arg arg;
+
+       /*
+        * During ep_insert() we already hold the ep->mtx for the tfile.
+        * Prevent re-aquisition.
+        */
+       arg.locked = wait && (wait->_qproc == ep_ptable_queue_proc);
+       arg.ep = ep;
 
        /* Insert inside our poll wait queue */
        poll_wait(file, &ep->poll_wait, wait);
@@ -827,7 +864,7 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
         * could re-enter here.
         */
        pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS,
-                                  ep_poll_readyevents_proc, ep, ep, current);
+                                  ep_poll_readyevents_proc, &arg, ep, current);
 
        return pollflags != -1 ? pollflags : 0;
 }
@@ -872,7 +909,6 @@ static const struct file_operations eventpoll_fops = {
  */
 void eventpoll_release_file(struct file *file)
 {
-       struct list_head *lsthead = &file->f_ep_links;
        struct eventpoll *ep;
        struct epitem *epi;
 
@@ -890,17 +926,12 @@ void eventpoll_release_file(struct file *file)
         * Besides, ep_remove() acquires the lock, so we can't hold it here.
         */
        mutex_lock(&epmutex);
-
-       while (!list_empty(lsthead)) {
-               epi = list_first_entry(lsthead, struct epitem, fllink);
-
+       list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) {
                ep = epi->ep;
-               list_del_init(&epi->fllink);
                mutex_lock_nested(&ep->mtx, 0);
                ep_remove(ep, epi);
                mutex_unlock(&ep->mtx);
        }
-
        mutex_unlock(&epmutex);
 }
 
@@ -1138,7 +1169,9 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
        struct file *child_file;
        struct epitem *epi;
 
-       list_for_each_entry(epi, &file->f_ep_links, fllink) {
+       /* CTL_DEL can remove links here, but that can't increase our count */
+       rcu_read_lock();
+       list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) {
                child_file = epi->ep->file;
                if (is_file_epoll(child_file)) {
                        if (list_empty(&child_file->f_ep_links)) {
@@ -1160,6 +1193,7 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
                                "file is not an ep!\n");
                }
        }
+       rcu_read_unlock();
        return error;
 }
 
@@ -1231,7 +1265,7 @@ static noinline void ep_destroy_wakeup_source(struct epitem *epi)
  * Must be called with "mtx" held.
  */
 static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
-                    struct file *tfile, int fd)
+                    struct file *tfile, int fd, int full_check)
 {
        int error, revents, pwake = 0;
        unsigned long flags;
@@ -1286,7 +1320,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 
        /* Add the current item to the list of active epoll hook for this file */
        spin_lock(&tfile->f_lock);
-       list_add_tail(&epi->fllink, &tfile->f_ep_links);
+       list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
        spin_unlock(&tfile->f_lock);
 
        /*
@@ -1297,7 +1331,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 
        /* now check if we've created too many backpaths */
        error = -EINVAL;
-       if (reverse_path_check())
+       if (full_check && reverse_path_check())
                goto error_remove_epi;
 
        /* We have to drop the new item inside our item list to keep track of it */
@@ -1327,8 +1361,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 
 error_remove_epi:
        spin_lock(&tfile->f_lock);
-       if (ep_is_linked(&epi->fllink))
-               list_del_init(&epi->fllink);
+       list_del_rcu(&epi->fllink);
        spin_unlock(&tfile->f_lock);
 
        rb_erase(&epi->rbn, &ep->rbr);
@@ -1521,7 +1554,7 @@ static int ep_send_events(struct eventpoll *ep,
        esed.maxevents = maxevents;
        esed.events = events;
 
-       return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0);
+       return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0, false);
 }
 
 static inline struct timespec ep_set_mstimeout(long ms)
@@ -1791,11 +1824,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                struct epoll_event __user *, event)
 {
        int error;
-       int did_lock_epmutex = 0;
+       int full_check = 0;
        struct fd f, tf;
        struct eventpoll *ep;
        struct epitem *epi;
        struct epoll_event epds;
+       struct eventpoll *tep = NULL;
 
        error = -EFAULT;
        if (ep_op_has_event(op) &&
@@ -1844,26 +1878,40 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
         * and hang them on the tfile_check_list, so we can check that we
         * haven't created too many possible wakeup paths.
         *
-        * We need to hold the epmutex across both ep_insert and ep_remove
-        * b/c we want to make sure we are looking at a coherent view of
-        * epoll network.
+        * We do not need to take the global 'epumutex' on EPOLL_CTL_ADD when
+        * the epoll file descriptor is attaching directly to a wakeup source,
+        * unless the epoll file descriptor is nested. The purpose of taking the
+        * 'epmutex' on add is to prevent complex toplogies such as loops and
+        * deep wakeup paths from forming in parallel through multiple
+        * EPOLL_CTL_ADD operations.
         */
-       if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
-               mutex_lock(&epmutex);
-               did_lock_epmutex = 1;
-       }
+       mutex_lock_nested(&ep->mtx, 0);
        if (op == EPOLL_CTL_ADD) {
-               if (is_file_epoll(tf.file)) {
-                       error = -ELOOP;
-                       if (ep_loop_check(ep, tf.file) != 0) {
-                               clear_tfile_check_list();
-                               goto error_tgt_fput;
+               if (!list_empty(&f.file->f_ep_links) ||
+                                               is_file_epoll(tf.file)) {
+                       full_check = 1;
+                       mutex_unlock(&ep->mtx);
+                       mutex_lock(&epmutex);
+                       if (is_file_epoll(tf.file)) {
+                               error = -ELOOP;
+                               if (ep_loop_check(ep, tf.file) != 0) {
+                                       clear_tfile_check_list();
+                                       goto error_tgt_fput;
+                               }
+                       } else
+                               list_add(&tf.file->f_tfile_llink,
+                                                       &tfile_check_list);
+                       mutex_lock_nested(&ep->mtx, 0);
+                       if (is_file_epoll(tf.file)) {
+                               tep = tf.file->private_data;
+                               mutex_lock_nested(&tep->mtx, 1);
                        }
-               } else
-                       list_add(&tf.file->f_tfile_llink, &tfile_check_list);
+               }
+       }
+       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
+               tep = tf.file->private_data;
+               mutex_lock_nested(&tep->mtx, 1);
        }
-
-       mutex_lock_nested(&ep->mtx, 0);
 
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
@@ -1877,10 +1925,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
        case EPOLL_CTL_ADD:
                if (!epi) {
                        epds.events |= POLLERR | POLLHUP;
-                       error = ep_insert(ep, &epds, tf.file, fd);
+                       error = ep_insert(ep, &epds, tf.file, fd, full_check);
                } else
                        error = -EEXIST;
-               clear_tfile_check_list();
+               if (full_check)
+                       clear_tfile_check_list();
                break;
        case EPOLL_CTL_DEL:
                if (epi)
@@ -1896,10 +1945,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                        error = -ENOENT;
                break;
        }
+       if (tep != NULL)
+               mutex_unlock(&tep->mtx);
        mutex_unlock(&ep->mtx);
 
 error_tgt_fput:
-       if (did_lock_epmutex)
+       if (full_check)
                mutex_unlock(&epmutex);
 
        fdput(tf);
index be4c81c7251c4b832b40980483bedf340456e954..977319fd77f39de88ef66979d1de95f7d846f9a6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1664,6 +1664,12 @@ int __get_dumpable(unsigned long mm_flags)
        return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret;
 }
 
+/*
+ * This returns the actual value of the suid_dumpable flag. For things
+ * that are using this for checking for privilege transitions, it must
+ * test against SUID_DUMP_USER rather than treating it as a boolean
+ * value.
+ */
 int get_dumpable(struct mm_struct *mm)
 {
        return __get_dumpable(mm->flags);
index 09c11329a17c6b3b6d4e2297faff09103e21e55c..1f4a10ece2f1249d5ae9991bfdde4874019b3462 100644 (file)
 struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
-       unsigned long *older_than_this;
+       /*
+        * Write only inodes dirtied before this time. Don't forget to set
+        * older_than_this_is_set when you set this.
+        */
+       unsigned long older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
+       unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
 
        struct list_head list;          /* pending work list */
@@ -247,10 +252,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
        int do_sb_sort = 0;
        int moved = 0;
 
+       WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (work->older_than_this &&
-                   inode_dirtied_after(inode, *work->older_than_this))
+               if (inode_dirtied_after(inode, work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@ -734,6 +739,8 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
+               .older_than_this = jiffies,
+               .older_than_this_is_set = 1,
        };
 
        spin_lock(&wb->list_lock);
@@ -792,12 +799,13 @@ static long wb_writeback(struct bdi_writeback *wb,
 {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
-       unsigned long oldest_jif;
        struct inode *inode;
        long progress;
 
-       oldest_jif = jiffies;
-       work->older_than_this = &oldest_jif;
+       if (!work->older_than_this_is_set) {
+               work->older_than_this = jiffies;
+               work->older_than_this_is_set = 1;
+       }
 
        spin_lock(&wb->list_lock);
        for (;;) {
@@ -831,10 +839,10 @@ static long wb_writeback(struct bdi_writeback *wb,
                 * safe.
                 */
                if (work->for_kupdate) {
-                       oldest_jif = jiffies -
+                       work->older_than_this = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
-                       oldest_jif = jiffies;
+                       work->older_than_this = jiffies;
 
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@ -1346,18 +1354,21 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
 
 /**
  * sync_inodes_sb      -       sync sb inode pages
- * @sb: the superblock
+ * @sb:                        the superblock
+ * @older_than_this:   timestamp
  *
  * This function writes and waits on any dirty inode belonging to this
- * super_block.
+ * superblock that has been dirtied before given timestamp.
  */
-void sync_inodes_sb(struct super_block *sb)
+void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
+               .older_than_this = older_than_this,
+               .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,
index 2a1d712f85dccfb5bb2983615e84278a1c4923e7..f6bd266d70b55d8273fcffc362f347c336237ae1 100644 (file)
@@ -153,11 +153,6 @@ struct hfs_btree_header_rec {
        u32 reserved3[16];
 } __packed;
 
-#define HFS_NODE_INDEX 0x00    /* An internal (index) node */
-#define HFS_NODE_HEADER        0x01    /* The tree header node (node 0) */
-#define HFS_NODE_MAP           0x02    /* Holds part of the bitmap of used nodes */
-#define HFS_NODE_LEAF          0xFF    /* A leaf (ndNHeight==1) node */
-
 #define BTREE_ATTR_BADCLOSE    0x00000001      /* b-tree not closed properly. not
                                                   used by hfsplus. */
 #define HFS_TREE_BIGKEYS       0x00000002      /* key length is u16 instead of u8.
index 0c6540c91167b354bf26fb743e28bd583c6aea0b..0fcec8b2a90b84160ed4c8109aa8dcda912487e7 100644 (file)
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 
+/*
+ * Initial source code of clump size calculation is gotten
+ * from http://opensource.apple.com/tarballs/diskdev_cmds/
+ */
+#define CLUMP_ENTRIES  15
+
+static short clumptbl[CLUMP_ENTRIES * 3] = {
+/*
+ *         Volume      Attributes       Catalog         Extents
+ *          Size       Clump (MB)      Clump (MB)      Clump (MB)
+ */
+       /*   1GB */       4,              4,             4,
+       /*   2GB */       6,              6,             4,
+       /*   4GB */       8,              8,             4,
+       /*   8GB */      11,             11,             5,
+       /*
+        * For volumes 16GB and larger, we want to make sure that a full OS
+        * install won't require fragmentation of the Catalog or Attributes
+        * B-trees.  We do this by making the clump sizes sufficiently large,
+        * and by leaving a gap after the B-trees for them to grow into.
+        *
+        * For SnowLeopard 10A298, a FullNetInstall with all packages selected
+        * results in:
+        * Catalog B-tree Header
+        *      nodeSize:          8192
+        *      totalNodes:       31616
+        *      freeNodes:         1978
+        * (used = 231.55 MB)
+        * Attributes B-tree Header
+        *      nodeSize:          8192
+        *      totalNodes:       63232
+        *      freeNodes:          958
+        * (used = 486.52 MB)
+        *
+        * We also want Time Machine backup volumes to have a sufficiently
+        * large clump size to reduce fragmentation.
+        *
+        * The series of numbers for Catalog and Attribute form a geometric
+        * series. For Catalog (16GB to 512GB), each term is 8**(1/5) times
+        * the previous term.  For Attributes (16GB to 512GB), each term is
+        * 4**(1/5) times the previous term.  For 1TB to 16TB, each term is
+        * 2**(1/5) times the previous term.
+        */
+       /*  16GB */      64,             32,             5,
+       /*  32GB */      84,             49,             6,
+       /*  64GB */     111,             74,             7,
+       /* 128GB */     147,            111,             8,
+       /* 256GB */     194,            169,             9,
+       /* 512GB */     256,            256,            11,
+       /*   1TB */     294,            294,            14,
+       /*   2TB */     338,            338,            16,
+       /*   4TB */     388,            388,            20,
+       /*   8TB */     446,            446,            25,
+       /*  16TB */     512,            512,            32
+};
+
+u32 hfsplus_calc_btree_clump_size(u32 block_size, u32 node_size,
+                                       u64 sectors, int file_id)
+{
+       u32 mod = max(node_size, block_size);
+       u32 clump_size;
+       int column;
+       int i;
+
+       /* Figure out which column of the above table to use for this file. */
+       switch (file_id) {
+       case HFSPLUS_ATTR_CNID:
+               column = 0;
+               break;
+       case HFSPLUS_CAT_CNID:
+               column = 1;
+               break;
+       default:
+               column = 2;
+               break;
+       }
+
+       /*
+        * The default clump size is 0.8% of the volume size. And
+        * it must also be a multiple of the node and block size.
+        */
+       if (sectors < 0x200000) {
+               clump_size = sectors << 2;      /*  0.8 %  */
+               if (clump_size < (8 * node_size))
+                       clump_size = 8 * node_size;
+       } else {
+               /* turn exponent into table index... */
+               for (i = 0, sectors = sectors >> 22;
+                    sectors && (i < CLUMP_ENTRIES - 1);
+                    ++i, sectors = sectors >> 1) {
+                       /* empty body */
+               }
+
+               clump_size = clumptbl[column + (i) * 3] * 1024 * 1024;
+       }
+
+       /*
+        * Round the clump size to a multiple of node and block size.
+        * NOTE: This rounds down.
+        */
+       clump_size /= mod;
+       clump_size *= mod;
+
+       /*
+        * Rounding down could have rounded down to 0 if the block size was
+        * greater than the clump size.  If so, just use one block or node.
+        */
+       if (clump_size == 0)
+               clump_size = mod;
+
+       return clump_size;
+}
 
 /* Get a reference to a B*Tree and do some initial checks */
 struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
index 2b9cd01696e2081a7a003ff3e52d261eb51db51c..08846425b67ffa112b7978650e1521b74955a1dc 100644 (file)
@@ -126,6 +126,14 @@ struct hfs_bnode {
 #define HFS_BNODE_DIRTY                3
 #define HFS_BNODE_DELETED      4
 
+/*
+ * Attributes file states
+ */
+#define HFSPLUS_EMPTY_ATTR_TREE                0
+#define HFSPLUS_CREATING_ATTR_TREE     1
+#define HFSPLUS_VALID_ATTR_TREE                2
+#define HFSPLUS_FAILED_ATTR_TREE       3
+
 /*
  * HFS+ superblock info (built from Volume Header on disk)
  */
@@ -141,6 +149,7 @@ struct hfsplus_sb_info {
        struct hfs_btree *ext_tree;
        struct hfs_btree *cat_tree;
        struct hfs_btree *attr_tree;
+       atomic_t attr_tree_state;
        struct inode *alloc_file;
        struct inode *hidden_dir;
        struct nls_table *nls;
@@ -380,6 +389,7 @@ int hfsplus_block_allocate(struct super_block *, u32, u32, u32 *);
 int hfsplus_block_free(struct super_block *, u32, u32);
 
 /* btree.c */
+u32 hfsplus_calc_btree_clump_size(u32, u32, u64, int);
 struct hfs_btree *hfs_btree_open(struct super_block *, u32);
 void hfs_btree_close(struct hfs_btree *);
 int hfs_btree_write(struct hfs_btree *);
index 452ede01b036c4de551e2cb9a723855bf066070b..8ffb3a8ffe75b9d6374cb9198d83d5dce5553457 100644 (file)
@@ -156,10 +156,10 @@ struct hfs_bnode_desc {
 } __packed;
 
 /* HFS+ BTree node types */
-#define HFS_NODE_INDEX 0x00
-#define HFS_NODE_HEADER        0x01
-#define HFS_NODE_MAP   0x02
-#define HFS_NODE_LEAF  0xFF
+#define HFS_NODE_INDEX 0x00    /* An internal (index) node */
+#define HFS_NODE_HEADER        0x01    /* The tree header node (node 0) */
+#define HFS_NODE_MAP   0x02    /* Holds part of the bitmap of used nodes */
+#define HFS_NODE_LEAF  0xFF    /* A leaf (ndNHeight==1) node */
 
 /* HFS+ BTree header */
 struct hfs_btree_header_rec {
@@ -187,6 +187,9 @@ struct hfs_btree_header_rec {
 /* HFS+ BTree misc info */
 #define HFSPLUS_TREE_HEAD 0
 #define HFSPLUS_NODE_MXSZ 32768
+#define HFSPLUS_ATTR_TREE_NODE_SIZE            8192
+#define HFSPLUS_BTREE_HDR_NODE_RECS_COUNT      3
+#define HFSPLUS_BTREE_HDR_USER_BYTES           128
 
 /* Some special File ID numbers (stolen from hfs.h) */
 #define HFSPLUS_POR_CNID               1       /* Parent Of the Root */
index 4c4d142cf890a4cb7949467150d9aeb357fd6942..80875aa640efc0f5831daa3fb919940d8d85e25b 100644 (file)
@@ -474,12 +474,14 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                pr_err("failed to load catalog file\n");
                goto out_close_ext_tree;
        }
+       atomic_set(&sbi->attr_tree_state, HFSPLUS_EMPTY_ATTR_TREE);
        if (vhdr->attr_file.total_blocks != 0) {
                sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
                if (!sbi->attr_tree) {
                        pr_err("failed to load attributes file\n");
                        goto out_close_cat_tree;
                }
+               atomic_set(&sbi->attr_tree_state, HFSPLUS_VALID_ATTR_TREE);
        }
        sb->s_xattr = hfsplus_xattr_handlers;
 
index bd8471fb9a6a80fdf74abdbd673714931c0b7867..efc85b1377cce60c5d3e47853d60777f576c7a27 100644 (file)
@@ -127,6 +127,208 @@ static int can_set_xattr(struct inode *inode, const char *name,
        return 0;
 }
 
+static void hfsplus_init_header_node(struct inode *attr_file,
+                                       u32 clump_size,
+                                       char *buf, size_t node_size)
+{
+       struct hfs_bnode_desc *desc;
+       struct hfs_btree_header_rec *head;
+       u16 offset;
+       __be16 *rec_offsets;
+       u32 hdr_node_map_rec_bits;
+       char *bmp;
+       u32 used_nodes;
+       u32 used_bmp_bytes;
+
+       hfs_dbg(ATTR_MOD, "init_hdr_attr_file: clump %u, node_size %zu\n",
+                               clump_size, node_size);
+
+       /* The end of the node contains list of record offsets */
+       rec_offsets = (__be16 *)(buf + node_size);
+
+       desc = (struct hfs_bnode_desc *)buf;
+       desc->type = HFS_NODE_HEADER;
+       desc->num_recs = cpu_to_be16(HFSPLUS_BTREE_HDR_NODE_RECS_COUNT);
+       offset = sizeof(struct hfs_bnode_desc);
+       *--rec_offsets = cpu_to_be16(offset);
+
+       head = (struct hfs_btree_header_rec *)(buf + offset);
+       head->node_size = cpu_to_be16(node_size);
+       head->node_count = cpu_to_be32(i_size_read(attr_file) / node_size);
+       head->free_nodes = cpu_to_be32(be32_to_cpu(head->node_count) - 1);
+       head->clump_size = cpu_to_be32(clump_size);
+       head->attributes |= cpu_to_be32(HFS_TREE_BIGKEYS | HFS_TREE_VARIDXKEYS);
+       head->max_key_len = cpu_to_be16(HFSPLUS_ATTR_KEYLEN - sizeof(u16));
+       offset += sizeof(struct hfs_btree_header_rec);
+       *--rec_offsets = cpu_to_be16(offset);
+       offset += HFSPLUS_BTREE_HDR_USER_BYTES;
+       *--rec_offsets = cpu_to_be16(offset);
+
+       hdr_node_map_rec_bits = 8 * (node_size - offset - (4 * sizeof(u16)));
+       if (be32_to_cpu(head->node_count) > hdr_node_map_rec_bits) {
+               u32 map_node_bits;
+               u32 map_nodes;
+
+               desc->next = cpu_to_be32(be32_to_cpu(head->leaf_tail) + 1);
+               map_node_bits = 8 * (node_size - sizeof(struct hfs_bnode_desc) -
+                                       (2 * sizeof(u16)) - 2);
+               map_nodes = (be32_to_cpu(head->node_count) -
+                               hdr_node_map_rec_bits +
+                               (map_node_bits - 1)) / map_node_bits;
+               be32_add_cpu(&head->free_nodes, 0 - map_nodes);
+       }
+
+       bmp = buf + offset;
+       used_nodes =
+               be32_to_cpu(head->node_count) - be32_to_cpu(head->free_nodes);
+       used_bmp_bytes = used_nodes / 8;
+       if (used_bmp_bytes) {
+               memset(bmp, 0xFF, used_bmp_bytes);
+               bmp += used_bmp_bytes;
+               used_nodes %= 8;
+       }
+       *bmp = ~(0xFF >> used_nodes);
+       offset += hdr_node_map_rec_bits / 8;
+       *--rec_offsets = cpu_to_be16(offset);
+}
+
+static int hfsplus_create_attributes_file(struct super_block *sb)
+{
+       int err = 0;
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       struct inode *attr_file;
+       struct hfsplus_inode_info *hip;
+       u32 clump_size;
+       u16 node_size = HFSPLUS_ATTR_TREE_NODE_SIZE;
+       char *buf;
+       int index, written;
+       struct address_space *mapping;
+       struct page *page;
+       int old_state = HFSPLUS_EMPTY_ATTR_TREE;
+
+       hfs_dbg(ATTR_MOD, "create_attr_file: ino %d\n", HFSPLUS_ATTR_CNID);
+
+check_attr_tree_state_again:
+       switch (atomic_read(&sbi->attr_tree_state)) {
+       case HFSPLUS_EMPTY_ATTR_TREE:
+               if (old_state != atomic_cmpxchg(&sbi->attr_tree_state,
+                                               old_state,
+                                               HFSPLUS_CREATING_ATTR_TREE))
+                       goto check_attr_tree_state_again;
+               break;
+       case HFSPLUS_CREATING_ATTR_TREE:
+               /*
+                * This state means that another thread is in process
+                * of AttributesFile creation. Theoretically, it is
+                * possible to be here. But really __setxattr() method
+                * first of all calls hfs_find_init() for lookup in
+                * B-tree of CatalogFile. This method locks mutex of
+                * CatalogFile's B-tree. As a result, if some thread
+                * is inside AttributedFile creation operation then
+                * another threads will be waiting unlocking of
+                * CatalogFile's B-tree's mutex. However, if code will
+                * change then we will return error code (-EAGAIN) from
+                * here. Really, it means that first try to set of xattr
+                * fails with error but second attempt will have success.
+                */
+               return -EAGAIN;
+       case HFSPLUS_VALID_ATTR_TREE:
+               return 0;
+       case HFSPLUS_FAILED_ATTR_TREE:
+               return -EOPNOTSUPP;
+       default:
+               BUG();
+       }
+
+       attr_file = hfsplus_iget(sb, HFSPLUS_ATTR_CNID);
+       if (IS_ERR(attr_file)) {
+               pr_err("failed to load attributes file\n");
+               return PTR_ERR(attr_file);
+       }
+
+       BUG_ON(i_size_read(attr_file) != 0);
+
+       hip = HFSPLUS_I(attr_file);
+
+       clump_size = hfsplus_calc_btree_clump_size(sb->s_blocksize,
+                                                   node_size,
+                                                   sbi->sect_count,
+                                                   HFSPLUS_ATTR_CNID);
+
+       mutex_lock(&hip->extents_lock);
+       hip->clump_blocks = clump_size >> sbi->alloc_blksz_shift;
+       mutex_unlock(&hip->extents_lock);
+
+       if (sbi->free_blocks <= (hip->clump_blocks << 1)) {
+               err = -ENOSPC;
+               goto end_attr_file_creation;
+       }
+
+       while (hip->alloc_blocks < hip->clump_blocks) {
+               err = hfsplus_file_extend(attr_file);
+               if (unlikely(err)) {
+                       pr_err("failed to extend attributes file\n");
+                       goto end_attr_file_creation;
+               }
+               hip->phys_size = attr_file->i_size =
+                       (loff_t)hip->alloc_blocks << sbi->alloc_blksz_shift;
+               hip->fs_blocks = hip->alloc_blocks << sbi->fs_shift;
+               inode_set_bytes(attr_file, attr_file->i_size);
+       }
+
+       buf = kzalloc(node_size, GFP_NOFS);
+       if (!buf) {
+               pr_err("failed to allocate memory for header node\n");
+               err = -ENOMEM;
+               goto end_attr_file_creation;
+       }
+
+       hfsplus_init_header_node(attr_file, clump_size, buf, node_size);
+
+       mapping = attr_file->i_mapping;
+
+       index = 0;
+       written = 0;
+       for (; written < node_size; index++, written += PAGE_CACHE_SIZE) {
+               void *kaddr;
+
+               page = read_mapping_page(mapping, index, NULL);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       goto failed_header_node_init;
+               }
+
+               kaddr = kmap_atomic(page);
+               memcpy(kaddr, buf + written,
+                       min_t(size_t, PAGE_CACHE_SIZE, node_size - written));
+               kunmap_atomic(kaddr);
+
+               set_page_dirty(page);
+               page_cache_release(page);
+       }
+
+       hfsplus_mark_inode_dirty(attr_file, HFSPLUS_I_ATTR_DIRTY);
+
+       sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
+       if (!sbi->attr_tree)
+               pr_err("failed to load attributes file\n");
+
+failed_header_node_init:
+       kfree(buf);
+
+end_attr_file_creation:
+       iput(attr_file);
+
+       if (!err)
+               atomic_set(&sbi->attr_tree_state, HFSPLUS_VALID_ATTR_TREE);
+       else if (err == -ENOSPC)
+               atomic_set(&sbi->attr_tree_state, HFSPLUS_EMPTY_ATTR_TREE);
+       else
+               atomic_set(&sbi->attr_tree_state, HFSPLUS_FAILED_ATTR_TREE);
+
+       return err;
+}
+
 int __hfsplus_setxattr(struct inode *inode, const char *name,
                        const void *value, size_t size, int flags)
 {
@@ -211,8 +413,9 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
        }
 
        if (!HFSPLUS_SB(inode->i_sb)->attr_tree) {
-               err = -EOPNOTSUPP;
-               goto end_setxattr;
+               err = hfsplus_create_attributes_file(inode->i_sb);
+               if (unlikely(err))
+                       goto end_setxattr;
        }
 
        if (hfsplus_attr_exists(inode, name)) {
index 17e6bdde96c5e4707a29906e207e981761ca49c8..dc7411fe185d99652cc98f93436e1b46bdfd380d 100644 (file)
@@ -1025,7 +1025,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
                for(i = count;  i < (num_got + count); i++) {
                        bhs[i] = sb_getblk(osb->sb, first_blkno);
                        if (bhs[i] == NULL) {
-                               status = -EIO;
+                               status = -ENOMEM;
                                mlog_errno(status);
                                goto bail;
                        }
index f37d3c0e20535eacce542c7184f48d8b509884a2..aeb44e879c51fe35ec91b221ade792d8f54ced74 100644 (file)
@@ -80,6 +80,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
 
        if ((u64)iblock >= ocfs2_clusters_to_blocks(inode->i_sb,
                                                    le32_to_cpu(fe->i_clusters))) {
+               err = -ENOMEM;
                mlog(ML_ERROR, "block offset is outside the allocated size: "
                     "%llu\n", (unsigned long long)iblock);
                goto bail;
@@ -92,6 +93,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
                            iblock;
                buffer_cache_bh = sb_getblk(osb->sb, blkno);
                if (!buffer_cache_bh) {
+                       err = -ENOMEM;
                        mlog(ML_ERROR, "couldn't getblock for symlink!\n");
                        goto bail;
                }
@@ -592,26 +594,11 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        ocfs2_rw_unlock(inode, level);
 }
 
-/*
- * ocfs2_invalidatepage() and ocfs2_releasepage() are shamelessly stolen
- * from ext3.  PageChecked() bits have been removed as OCFS2 does not
- * do journalled data.
- */
-static void ocfs2_invalidatepage(struct page *page, unsigned int offset,
-                                unsigned int length)
-{
-       journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
-
-       jbd2_journal_invalidatepage(journal, page, offset, length);
-}
-
 static int ocfs2_releasepage(struct page *page, gfp_t wait)
 {
-       journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
-
        if (!page_has_buffers(page))
                return 0;
-       return jbd2_journal_try_to_free_buffers(journal, page, wait);
+       return try_to_free_buffers(page);
 }
 
 static ssize_t ocfs2_direct_IO(int rw,
@@ -1802,8 +1789,7 @@ try_again:
                        data_ac->ac_resv = &OCFS2_I(inode)->ip_la_data_resv;
 
                credits = ocfs2_calc_extend_credits(inode->i_sb,
-                                                   &di->id2.i_list,
-                                                   clusters_to_alloc);
+                                                   &di->id2.i_list);
 
        }
 
@@ -1897,10 +1883,14 @@ out_commit:
 out:
        ocfs2_free_write_ctxt(wc);
 
-       if (data_ac)
+       if (data_ac) {
                ocfs2_free_alloc_context(data_ac);
-       if (meta_ac)
+               data_ac = NULL;
+       }
+       if (meta_ac) {
                ocfs2_free_alloc_context(meta_ac);
+               meta_ac = NULL;
+       }
 
        if (ret == -ENOSPC && try_free) {
                /*
@@ -2087,7 +2077,7 @@ const struct address_space_operations ocfs2_aops = {
        .write_end              = ocfs2_write_end,
        .bmap                   = ocfs2_bmap,
        .direct_IO              = ocfs2_direct_IO,
-       .invalidatepage         = ocfs2_invalidatepage,
+       .invalidatepage         = block_invalidatepage,
        .releasepage            = ocfs2_releasepage,
        .migratepage            = buffer_migrate_page,
        .is_partially_uptodate  = block_is_partially_uptodate,
index 5d18ad10c27fc044ae240a5c147c8f3e0b146ae5..5b704c63a103018ddb8a56663e42edd09d6d40ff 100644 (file)
@@ -115,7 +115,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
                if (bhs[i] == NULL) {
                        bhs[i] = sb_getblk(osb->sb, block++);
                        if (bhs[i] == NULL) {
-                               status = -EIO;
+                               status = -ENOMEM;
                                mlog_errno(status);
                                goto bail;
                        }
@@ -214,7 +214,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                        bhs[i] = sb_getblk(sb, block++);
                        if (bhs[i] == NULL) {
                                ocfs2_metadata_cache_io_unlock(ci);
-                               status = -EIO;
+                               status = -ENOMEM;
                                mlog_errno(status);
                                goto bail;
                        }
index 363f0dcc924fb5b05c433b98e43c5ad9038ddc3b..73920ffda05b331c85ef1760d97083d1590a4a16 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
 
 #include "heartbeat.h"
 #include "tcp.h"
@@ -282,15 +283,6 @@ struct o2hb_bio_wait_ctxt {
        int               wc_error;
 };
 
-static int o2hb_pop_count(void *map, int count)
-{
-       int i = -1, pop = 0;
-
-       while ((i = find_next_bit(map, count, i + 1)) < count)
-               pop++;
-       return pop;
-}
-
 static void o2hb_write_timeout(struct work_struct *work)
 {
        int failed, quorum;
@@ -307,9 +299,9 @@ static void o2hb_write_timeout(struct work_struct *work)
                spin_lock_irqsave(&o2hb_live_lock, flags);
                if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
                        set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
-               failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+               failed = bitmap_weight(o2hb_failed_region_bitmap,
                                        O2NM_MAX_REGIONS);
-               quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+               quorum = bitmap_weight(o2hb_quorum_region_bitmap,
                                        O2NM_MAX_REGIONS);
                spin_unlock_irqrestore(&o2hb_live_lock, flags);
 
@@ -765,7 +757,7 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg)
         * If global heartbeat active, unpin all regions if the
         * region count > CUT_OFF
         */
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
                o2hb_region_unpin(NULL);
 unlock:
@@ -954,23 +946,9 @@ out:
        return changed;
 }
 
-/* This could be faster if we just implmented a find_last_bit, but I
- * don't think the circumstances warrant it. */
-static int o2hb_highest_node(unsigned long *nodes,
-                            int numbits)
+static int o2hb_highest_node(unsigned long *nodes, int numbits)
 {
-       int highest, node;
-
-       highest = numbits;
-       node = -1;
-       while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
-               if (node >= numbits)
-                       break;
-
-               highest = node;
-       }
-
-       return highest;
+       return find_last_bit(nodes, numbits);
 }
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
@@ -1829,7 +1807,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        live_threshold = O2HB_LIVE_THRESHOLD;
        if (o2hb_global_heartbeat_active()) {
                spin_lock(&o2hb_live_lock);
-               if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+               if (bitmap_weight(o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
                        live_threshold <<= 1;
                spin_unlock(&o2hb_live_lock);
        }
@@ -2180,7 +2158,7 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        if (!o2hb_dependent_users)
                goto unlock;
 
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
                o2hb_region_pin(NULL);
 
@@ -2480,7 +2458,7 @@ static int o2hb_region_inc_user(const char *region_uuid)
        if (o2hb_dependent_users > 1)
                goto unlock;
 
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
                ret = o2hb_region_pin(NULL);
 
index baa2b9ef7eef90094dbd3ef8d76f6a6e1df64224..2260fb9e650831fef349ce2c6f6dcd878ffa45d2 100644 (file)
@@ -199,7 +199,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 #define mlog_errno(st) do {                                            \
        int _st = (st);                                                 \
        if (_st != -ERESTARTSYS && _st != -EINTR &&                     \
-           _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)                \
+           _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&              \
+           _st != -EDQUOT)                                             \
                mlog(ML_ERROR, "status = %lld\n", (long long)_st);      \
 } while (0)
 
index 30544ce8e9f78cc66cc0eb61387f84b21cef4309..91a7e85ac8fdc8f6d25944d5b3552a39e20ab86b 100644 (file)
@@ -2349,7 +2349,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
 
        dx_root_bh = sb_getblk(osb->sb, dr_blkno);
        if (dx_root_bh == NULL) {
-               ret = -EIO;
+               ret = -ENOMEM;
                goto out;
        }
        ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dx_root_bh);
@@ -2422,7 +2422,7 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
        for (i = 0; i < num_dx_leaves; i++) {
                bh = sb_getblk(osb->sb, start_blk + i);
                if (bh == NULL) {
-                       ret = -EIO;
+                       ret = -ENOMEM;
                        goto out;
                }
                dx_leaves[i] = bh;
@@ -2929,7 +2929,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
        dirdata_bh = sb_getblk(sb, blkno);
        if (!dirdata_bh) {
-               ret = -EIO;
+               ret = -ENOMEM;
                mlog_errno(ret);
                goto out_commit;
        }
@@ -3159,7 +3159,7 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
 
        *new_bh = sb_getblk(sb, p_blkno);
        if (!*new_bh) {
-               status = -EIO;
+               status = -ENOMEM;
                mlog_errno(status);
                goto bail;
        }
@@ -3284,7 +3284,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                if (ocfs2_dir_resv_allowed(osb))
                        data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv;
 
-               credits = ocfs2_calc_extend_credits(sb, el, 1);
+               credits = ocfs2_calc_extend_credits(sb, el);
        } else {
                spin_unlock(&OCFS2_I(dir)->ip_lock);
                credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
@@ -3716,7 +3716,7 @@ static int ocfs2_dx_dir_rebalance_credits(struct ocfs2_super *osb,
 {
        int credits = ocfs2_clusters_to_blocks(osb->sb, 2);
 
-       credits += ocfs2_calc_extend_credits(osb->sb, &dx_root->dr_list, 1);
+       credits += ocfs2_calc_extend_credits(osb->sb, &dx_root->dr_list);
        credits += ocfs2_quota_trans_credits(osb->sb);
        return credits;
 }
index cf0f103963b1a05192cc124e9976cbc5a318b64b..af3f7aa73e13a007d06fd528d8c8d101d2553087 100644 (file)
@@ -1885,8 +1885,10 @@ ok:
                         * up nodes that this node contacted */
                        while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
                                                    nn+1)) < O2NM_MAX_NODES) {
-                               if (nn != dlm->node_num && nn != assert->node_idx)
+                               if (nn != dlm->node_num && nn != assert->node_idx) {
                                        master_request = 1;
+                                       break;
+                               }
                        }
                }
                mle->master = assert->node_idx;
@@ -2354,6 +2356,10 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
        assert_spin_locked(&res->spinlock);
 
+       /* delay migration when the lockres is in MIGRATING state */
+       if (res->state & DLM_LOCK_RES_MIGRATING)
+               return 0;
+
        if (res->owner != dlm->node_num)
                return 0;
 
index 0b5adca1b1787bbc09284255417979c0c13f3f32..7035af09cc036bcae90cb2872228044a17866330 100644 (file)
@@ -1886,6 +1886,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                if (ml->type == LKM_NLMODE)
                        goto skip_lvb;
 
+               /*
+                * If the lock is in the blocked list it can't have a valid lvb,
+                * so skip it
+                */
+               if (ml->list == DLM_BLOCKED_LIST)
+                       goto skip_lvb;
+
                if (!dlm_lvb_is_empty(mres->lvb)) {
                        if (lksb->flags & DLM_LKSB_PUT_LVB) {
                                /* other node was trying to update
index d71903c6068b94f37836854762691a7a1c9d9f12..6fff128cad16164e0f10ca614db618e0af60768f 100644 (file)
@@ -580,7 +580,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
        int did_quota = 0;
 
        /*
-        * This function only exists for file systems which don't
+        * Unwritten extent only exists for file systems which
         * support holes.
         */
        BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
@@ -603,8 +603,7 @@ restart_all:
                goto leave;
        }
 
-       credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list,
-                                           clusters_to_add);
+       credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list);
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
index 0b479bab36713ec3ef147c314fe2473b08ed1d9e..9ff4e8cf9d972857a79e07a628116084bc6ba506 100644 (file)
@@ -524,8 +524,7 @@ static inline int ocfs2_calc_dxi_expand_credits(struct super_block *sb)
  * the result may be wrong.
  */
 static inline int ocfs2_calc_extend_credits(struct super_block *sb,
-                                           struct ocfs2_extent_list *root_el,
-                                           u32 bits_wanted)
+                                           struct ocfs2_extent_list *root_el)
 {
        int bitmap_blocks, sysfile_bitmap_blocks, extent_blocks;
 
index 3d3f3c83065ca3ed51d9dac690bac2e2012a36f9..631a98213474406b339908968bf7e83157051d34 100644 (file)
@@ -201,8 +201,7 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
                }
        }
 
-       *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el,
-                                             clusters_to_move + 2);
+       *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
 
        mlog(0, "reserve metadata_blocks: %d, data_clusters: %u, credits: %d\n",
             extra_blocks, clusters_to_move, *credits);
@@ -1067,8 +1066,10 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
        if (status)
                return status;
 
-       if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE))
+       if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) {
+               status = -EPERM;
                goto out_drop;
+       }
 
        if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
                status = -EPERM;
@@ -1090,8 +1091,10 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
                goto out_free;
        }
 
-       if (range.me_start > i_size_read(inode))
+       if (range.me_start > i_size_read(inode)) {
+               status = -EINVAL;
                goto out_free;
+       }
 
        if (range.me_start + range.me_len > i_size_read(inode))
                        range.me_len = i_size_read(inode) - range.me_start;
index be3f8676a4385970f0edc92fff291c997c3d2823..4f791f6d27d0463f8bef77dc20a5f5274df8ddea 100644 (file)
@@ -489,7 +489,7 @@ static int __ocfs2_mknod_locked(struct inode *dir,
 
        *new_fe_bh = sb_getblk(osb->sb, fe_blkno);
        if (!*new_fe_bh) {
-               status = -EIO;
+               status = -ENOMEM;
                mlog_errno(status);
                goto leave;
        }
index bf4dfc14bb2c7cca75b618de73bfcaf656103ff2..55767e1ba72492431dcb3ae9fe204526d93f28d2 100644 (file)
@@ -612,6 +612,11 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
        }
 
        new_bh = sb_getblk(inode->i_sb, first_blkno);
+       if (!new_bh) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out_commit;
+       }
        ocfs2_set_new_buffer_uptodate(&new_tree->rf_ci, new_bh);
 
        ret = ocfs2_journal_access_rb(handle, &new_tree->rf_ci, new_bh,
@@ -1310,7 +1315,7 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 
        new_bh = sb_getblk(sb, blkno);
        if (new_bh == NULL) {
-               ret = -EIO;
+               ret = -ENOMEM;
                mlog_errno(ret);
                goto out;
        }
@@ -1561,7 +1566,7 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 
        new_bh = sb_getblk(sb, blkno);
        if (new_bh == NULL) {
-               ret = -EIO;
+               ret = -ENOMEM;
                mlog_errno(ret);
                goto out;
        }
@@ -2502,8 +2507,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
                ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
                *meta_add += ocfs2_extend_meta_needed(et.et_root_el);
                *credits += ocfs2_calc_extend_credits(sb,
-                                                     et.et_root_el,
-                                                     ref_blocks);
+                                                     et.et_root_el);
        } else {
                *credits += OCFS2_EXPAND_REFCOUNT_TREE_CREDITS;
                *meta_add += 1;
@@ -2874,8 +2878,7 @@ static int ocfs2_lock_refcount_allocators(struct super_block *sb,
                meta_add =
                        ocfs2_extend_meta_needed(et->et_root_el);
 
-       *credits += ocfs2_calc_extend_credits(sb, et->et_root_el,
-                                             num_clusters + 2);
+       *credits += ocfs2_calc_extend_credits(sb, et->et_root_el);
 
        ret = ocfs2_calc_refcount_meta_credits(sb, ref_ci, ref_root_bh,
                                               p_cluster, num_clusters,
@@ -3031,7 +3034,7 @@ int ocfs2_duplicate_clusters_by_jbd(handle_t *handle,
        for (i = 0; i < blocks; i++, old_block++, new_block++) {
                new_bh = sb_getblk(osb->sb, new_block);
                if (new_bh == NULL) {
-                       ret = -EIO;
+                       ret = -ENOMEM;
                        mlog_errno(ret);
                        break;
                }
@@ -3625,8 +3628,7 @@ int ocfs2_refcounted_xattr_delete_need(struct inode *inode,
 
                ocfs2_init_refcount_extent_tree(&et, ref_ci, ref_root_bh);
                *credits += ocfs2_calc_extend_credits(inode->i_sb,
-                                                     et.et_root_el,
-                                                     ref_blocks);
+                                                     et.et_root_el);
        }
 
 out:
index ec55add7604a0e964447efa954e4424bf1a39016..822ebc10f281057d9c6f5adc01c246042ef01cfd 100644 (file)
@@ -469,6 +469,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        struct ocfs2_chain_list *cl;
        struct ocfs2_chain_rec *cr;
        u16 cl_bpc;
+       u64 bg_ptr;
 
        if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
                return -EROFS;
@@ -513,7 +514,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        ret = ocfs2_verify_group_and_input(main_bm_inode, fe, input, group_bh);
        if (ret) {
                mlog_errno(ret);
-               goto out_unlock;
+               goto out_free_group_bh;
        }
 
        trace_ocfs2_group_add((unsigned long long)input->group,
@@ -523,7 +524,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        if (IS_ERR(handle)) {
                mlog_errno(PTR_ERR(handle));
                ret = -EINVAL;
-               goto out_unlock;
+               goto out_free_group_bh;
        }
 
        cl_bpc = le16_to_cpu(fe->id2.i_chain.cl_bpc);
@@ -538,12 +539,14 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        }
 
        group = (struct ocfs2_group_desc *)group_bh->b_data;
+       bg_ptr = le64_to_cpu(group->bg_next_group);
        group->bg_next_group = cr->c_blkno;
        ocfs2_journal_dirty(handle, group_bh);
 
        ret = ocfs2_journal_access_di(handle, INODE_CACHE(main_bm_inode),
                                      main_bm_bh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
+               group->bg_next_group = cpu_to_le64(bg_ptr);
                mlog_errno(ret);
                goto out_commit;
        }
@@ -574,8 +577,11 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
 
 out_commit:
        ocfs2_commit_trans(osb, handle);
-out_unlock:
+
+out_free_group_bh:
        brelse(group_bh);
+
+out_unlock:
        brelse(main_bm_bh);
 
        ocfs2_inode_unlock(main_bm_inode, 1);
index 39abf89697edfc296173dce40a3e5aab1575202b..cb7ec0b63ddc503939888d153c0b9617400d52f7 100644 (file)
@@ -643,7 +643,7 @@ error:
 
 #define FS_OCFS2_NM            1
 
-static ctl_table ocfs2_nm_table[] = {
+static struct ctl_table ocfs2_nm_table[] = {
        {
                .procname       = "hb_ctl_path",
                .data           = ocfs2_hb_ctl_path,
@@ -654,7 +654,7 @@ static ctl_table ocfs2_nm_table[] = {
        { }
 };
 
-static ctl_table ocfs2_mod_table[] = {
+static struct ctl_table ocfs2_mod_table[] = {
        {
                .procname       = "nm",
                .data           = NULL,
@@ -665,7 +665,7 @@ static ctl_table ocfs2_mod_table[] = {
        { }
 };
 
-static ctl_table ocfs2_kern_table[] = {
+static struct ctl_table ocfs2_kern_table[] = {
        {
                .procname       = "ocfs2",
                .data           = NULL,
@@ -676,7 +676,7 @@ static ctl_table ocfs2_kern_table[] = {
        { }
 };
 
-static ctl_table ocfs2_root_table[] = {
+static struct ctl_table ocfs2_root_table[] = {
        {
                .procname       = "fs",
                .data           = NULL,
index 5397c07ce6080b8f6e3c5917225eba98a070a4ba..2c91452c4047bc3a9ff324a3ba5e2e0fbfd7d09f 100644 (file)
@@ -481,7 +481,7 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle,
 
        bg_bh = sb_getblk(osb->sb, bg_blkno);
        if (!bg_bh) {
-               status = -EIO;
+               status = -ENOMEM;
                mlog_errno(status);
                goto bail;
        }
@@ -661,7 +661,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle,
 
        bg_bh = sb_getblk(osb->sb, bg_blkno);
        if (!bg_bh) {
-               status = -EIO;
+               status = -ENOMEM;
                mlog_errno(status);
                goto bail;
        }
index d4e81e4a9b0489de2eb66899eb23b9d87ea81ae5..c41492957aa5f4ab4f7aa7a056ac2715a352c2b7 100644 (file)
@@ -1848,8 +1848,8 @@ static int ocfs2_get_sector(struct super_block *sb,
 
        *bh = sb_getblk(sb, block);
        if (!*bh) {
-               mlog_errno(-EIO);
-               return -EIO;
+               mlog_errno(-ENOMEM);
+               return -ENOMEM;
        }
        lock_buffer(*bh);
        if (!buffer_dirty(*bh))
index 6ce0686eab7202b29cd9f29a39e6692b8a1d618a..f0a1326d9bba89812f5ae736938ca3cfbee1284d 100644 (file)
@@ -377,7 +377,7 @@ static int ocfs2_init_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
                bucket->bu_bhs[i] = sb_getblk(bucket->bu_inode->i_sb,
                                              xb_blkno + i);
                if (!bucket->bu_bhs[i]) {
-                       rc = -EIO;
+                       rc = -ENOMEM;
                        mlog_errno(rc);
                        break;
                }
@@ -754,8 +754,7 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,
                        BUG_ON(why == RESTART_META);
 
                        credits = ocfs2_calc_extend_credits(inode->i_sb,
-                                                           &vb->vb_xv->xr_list,
-                                                           clusters_to_add);
+                                                           &vb->vb_xv->xr_list);
                        status = ocfs2_extend_trans(handle, credits);
                        if (status < 0) {
                                status = -ENOMEM;
@@ -2865,6 +2864,12 @@ static int ocfs2_create_xattr_block(struct inode *inode,
        }
 
        new_bh = sb_getblk(inode->i_sb, first_blkno);
+       if (!new_bh) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto end;
+       }
+
        ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
 
        ret = ocfs2_journal_access_xb(ctxt->handle, INODE_CACHE(inode),
@@ -3040,8 +3045,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
                if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
                        clusters_add += new_clusters;
                        credits += ocfs2_calc_extend_credits(inode->i_sb,
-                                                       &def_xv.xv.xr_list,
-                                                       new_clusters);
+                                                       &def_xv.xv.xr_list);
                }
 
                goto meta_guess;
@@ -3106,8 +3110,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
                        if (!ocfs2_xattr_is_local(xe))
                                credits += ocfs2_calc_extend_credits(
                                                        inode->i_sb,
-                                                       &def_xv.xv.xr_list,
-                                                       new_clusters);
+                                                       &def_xv.xv.xr_list);
                        goto out;
                }
        }
@@ -3132,9 +3135,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
                        meta_add += ocfs2_extend_meta_needed(&xv->xr_list);
                        clusters_add += new_clusters - old_clusters;
                        credits += ocfs2_calc_extend_credits(inode->i_sb,
-                                                            &xv->xr_list,
-                                                            new_clusters -
-                                                            old_clusters);
+                                                            &xv->xr_list);
                        if (value_size >= OCFS2_XATTR_ROOT_SIZE)
                                goto out;
                }
@@ -3180,7 +3181,7 @@ meta_guess:
                                 &xb->xb_attrs.xb_root.xt_list;
                        meta_add += ocfs2_extend_meta_needed(el);
                        credits += ocfs2_calc_extend_credits(inode->i_sb,
-                                                            el, 1);
+                                                            el);
                } else
                        credits += OCFS2_SUBALLOC_ALLOC + 1;
 
@@ -6216,8 +6217,7 @@ static int ocfs2_value_metas_in_xattr_header(struct super_block *sb,
                          le16_to_cpu(xv->xr_list.l_next_free_rec);
 
                *credits += ocfs2_calc_extend_credits(sb,
-                                               &def_xv.xv.xr_list,
-                                               le32_to_cpu(xv->xr_clusters));
+                                               &def_xv.xv.xr_list);
 
                /*
                 * If the value is a tree with depth > 1, We don't go deep
@@ -6782,7 +6782,7 @@ static int ocfs2_lock_reflink_xattr_rec_allocators(
                metas.num_metas += ocfs2_extend_meta_needed(xt_et->et_root_el);
 
        *credits += ocfs2_calc_extend_credits(osb->sb,
-                                             xt_et->et_root_el, len);
+                                             xt_et->et_root_el);
 
        if (metas.num_metas) {
                ret = ocfs2_reserve_new_metadata_blocks(osb, metas.num_metas,
index 15af6222f8a4fb465251dd97610460a9bc79639e..2183fcf41d5933d576724a4016cccd3adb4ce645 100644 (file)
@@ -31,6 +31,10 @@ config PROC_FS
 config PROC_KCORE
        bool "/proc/kcore support" if !ARM
        depends on PROC_FS && MMU
+       help
+         Provides a virtual ELF core file of the live kernel.  This can
+         be read with gdb and other ELF tools.  No modifications can be
+         made using this mechanism.
 
 config PROC_VMCORE
        bool "/proc/vmcore support"
index 8eaa1ba793fc188879d405e768a81aedbaa4bf76..28955d4b7218e95a6ba7666111459b0382450786 100644 (file)
@@ -285,19 +285,23 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
        return rv;
 }
 
-static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
+static unsigned long
+proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
+                          unsigned long len, unsigned long pgoff,
+                          unsigned long flags)
 {
        struct proc_dir_entry *pde = PDE(file_inode(file));
        unsigned long rv = -EIO;
-       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long) = NULL;
+       unsigned long (*get_area)(struct file *, unsigned long, unsigned long,
+                                 unsigned long, unsigned long) = NULL;
        if (use_pde(pde)) {
 #ifdef CONFIG_MMU
-               get_unmapped_area = current->mm->get_unmapped_area;
+               get_area = current->mm->get_unmapped_area;
 #endif
                if (pde->proc_fops->get_unmapped_area)
-                       get_unmapped_area = pde->proc_fops->get_unmapped_area;
-               if (get_unmapped_area)
-                       rv = get_unmapped_area(file, orig_addr, len, pgoff, flags);
+                       get_area = pde->proc_fops->get_unmapped_area;
+               if (get_area)
+                       rv = get_area(file, orig_addr, len, pgoff, flags);
                unuse_pde(pde);
        }
        return rv;
index 06ea155e1a590530d0c16ee964107bcf54756995..5ed0e52d6aa02bcd4e4867bd1cd36f8633f9f2f1 100644 (file)
@@ -255,8 +255,7 @@ static int kcore_update_ram(void)
        end_pfn = 0;
        for_each_node_state(nid, N_MEMORY) {
                unsigned long node_end;
-               node_end  = NODE_DATA(nid)->node_start_pfn +
-                       NODE_DATA(nid)->node_spanned_pages;
+               node_end = node_end_pfn(nid);
                if (end_pfn < node_end)
                        end_pfn = node_end;
        }
index 59d85d608898354169520fb26209789b27888978..c805d5b69ba125a5ab57cee445520cc6b81c8522 100644 (file)
@@ -24,7 +24,6 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 {
        struct sysinfo i;
        unsigned long committed;
-       unsigned long allowed;
        struct vmalloc_info vmi;
        long cached;
        unsigned long pages[NR_LRU_LISTS];
@@ -37,8 +36,6 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
        si_meminfo(&i);
        si_swapinfo(&i);
        committed = percpu_counter_read_positive(&vm_committed_as);
-       allowed = ((totalram_pages - hugetlb_total_pages())
-               * sysctl_overcommit_ratio / 100) + total_swap_pages;
 
        cached = global_page_state(NR_FILE_PAGES) -
                        total_swapcache_pages() - i.bufferram;
@@ -147,7 +144,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
                K(global_page_state(NR_UNSTABLE_NFS)),
                K(global_page_state(NR_BOUNCE)),
                K(global_page_state(NR_WRITEBACK_TEMP)),
-               K(allowed),
+               K(vm_commit_limit()),
                K(committed),
                (unsigned long)VMALLOC_TOTAL >> 10,
                vmi.used >> 10,
index 390bdab01c3c782cc14b55c6d1ef35ebddcc4197..abbe825d20ffa3dd4b4516ab57408803e1247f4f 100644 (file)
@@ -561,6 +561,9 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
                [ilog2(VM_NONLINEAR)]   = "nl",
                [ilog2(VM_ARCH_1)]      = "ar",
                [ilog2(VM_DONTDUMP)]    = "dd",
+#ifdef CONFIG_MEM_SOFT_DIRTY
+               [ilog2(VM_SOFTDIRTY)]   = "sd",
+#endif
                [ilog2(VM_MIXEDMAP)]    = "mm",
                [ilog2(VM_HUGEPAGE)]    = "hg",
                [ilog2(VM_NOHUGEPAGE)]  = "nh",
@@ -1387,8 +1390,8 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        struct mm_struct *mm = vma->vm_mm;
        struct mm_walk walk = {};
        struct mempolicy *pol;
-       int n;
-       char buffer[50];
+       char buffer[64];
+       int nid;
 
        if (!mm)
                return 0;
@@ -1404,10 +1407,8 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        walk.mm = mm;
 
        pol = get_vma_policy(task, vma, vma->vm_start);
-       n = mpol_to_str(buffer, sizeof(buffer), pol);
+       mpol_to_str(buffer, sizeof(buffer), pol);
        mpol_cond_put(pol);
-       if (n < 0)
-               return n;
 
        seq_printf(m, "%08lx %s", vma->vm_start, buffer);
 
@@ -1460,9 +1461,9 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        if (md->writeback)
                seq_printf(m, " writeback=%lu", md->writeback);
 
-       for_each_node_state(n, N_MEMORY)
-               if (md->node[n])
-                       seq_printf(m, " N%d=%lu", n, md->node[n]);
+       for_each_node_state(nid, N_MEMORY)
+               if (md->node[nid])
+                       seq_printf(m, " N%d=%lu", nid, md->node[nid]);
 out:
        seq_putc(m, '\n');
 
index 6c0ca3b75758dac589160158968a14518231810a..f15537452231d003a05f99b6b28d3c63b85dc8f0 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
  * wait == 1 case since in that case write_inode() functions do
  * sync_dirty_buffer() and thus effectively write one block at a time.
  */
-static int __sync_filesystem(struct super_block *sb, int wait)
+static int __sync_filesystem(struct super_block *sb, int wait,
+                            unsigned long start)
 {
        if (wait)
-               sync_inodes_sb(sb);
+               sync_inodes_sb(sb, start);
        else
                writeback_inodes_sb(sb, WB_REASON_SYNC);
 
@@ -47,6 +48,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
 int sync_filesystem(struct super_block *sb)
 {
        int ret;
+       unsigned long start = jiffies;
 
        /*
         * We need to be protected against the filesystem going from
@@ -60,17 +62,17 @@ int sync_filesystem(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       ret = __sync_filesystem(sb, 0);
+       ret = __sync_filesystem(sb, 0, start);
        if (ret < 0)
                return ret;
-       return __sync_filesystem(sb, 1);
+       return __sync_filesystem(sb, 1, start);
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
        if (!(sb->s_flags & MS_RDONLY))
-               sync_inodes_sb(sb);
+               sync_inodes_sb(sb, *((unsigned long *)arg));
 }
 
 static void sync_fs_one_sb(struct super_block *sb, void *arg)
@@ -102,9 +104,10 @@ static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
 SYSCALL_DEFINE0(sync)
 {
        int nowait = 0, wait = 1;
+       unsigned long start = jiffies;
 
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       iterate_supers(sync_inodes_one_sb, NULL);
+       iterate_supers(sync_inodes_one_sb, &start);
        iterate_supers(sync_fs_one_sb, &nowait);
        iterate_supers(sync_fs_one_sb, &wait);
        iterate_bdevs(fdatawrite_one_bdev, NULL);
index 15188cc9944919e275e43e4978056efa91801343..8968f5036fa17a5cda24c1bfdd9d7c3ed1957ca1 100644 (file)
@@ -918,7 +918,7 @@ xfs_flush_inodes(
        struct super_block      *sb = mp->m_super;
 
        if (down_read_trylock(&sb->s_umount)) {
-               sync_inodes_sb(sb);
+               sync_inodes_sb(sb, jiffies);
                up_read(&sb->s_umount);
        }
 }
index 71c778033f575e53b106c0fa649202d0a6a5ee3a..998d4d544f182ee305ae779ec0bf5e4f8f2ef43e 100644 (file)
@@ -7,6 +7,9 @@
  * @addr: The address to base the search on
  * @offset: The bitnumber to start searching at
  * @size: The bitmap size in bits
+ *
+ * Returns the bit number for the next set bit
+ * If no bits are set, returns @size.
  */
 extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
                size, unsigned long offset);
@@ -18,6 +21,9 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
  * @addr: The address to base the search on
  * @offset: The bitnumber to start searching at
  * @size: The bitmap size in bits
+ *
+ * Returns the bit number of the next zero bit
+ * If no bits are zero, returns @size.
  */
 extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
                long size, unsigned long offset);
@@ -28,9 +34,10 @@ extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
 /**
  * find_first_bit - find the first set bit in a memory region
  * @addr: The address to start the search at
- * @size: The maximum size to search
+ * @size: The maximum number of bits to search
  *
  * Returns the bit number of the first set bit.
+ * If no bits are set, returns @size.
  */
 extern unsigned long find_first_bit(const unsigned long *addr,
                                    unsigned long size);
@@ -38,9 +45,10 @@ extern unsigned long find_first_bit(const unsigned long *addr,
 /**
  * find_first_zero_bit - find the first cleared bit in a memory region
  * @addr: The address to start the search at
- * @size: The maximum size to search
+ * @size: The maximum number of bits to search
  *
  * Returns the bit number of the first cleared bit.
+ * If no bits are zero, returns @size.
  */
 extern unsigned long find_first_zero_bit(const unsigned long *addr,
                                         unsigned long size);
index 790d3305a5a7ace2f0c363341b4a2da743d53f5d..fd8bf3219ef7bbc9af53a05e391215a978de1a19 100644 (file)
@@ -100,9 +100,6 @@ extern void setup_new_exec(struct linux_binprm * bprm);
 extern void would_dump(struct linux_binprm *, struct file *);
 
 extern int suid_dumpable;
-#define SUID_DUMP_DISABLE      0       /* No setuid dumping */
-#define SUID_DUMP_USER         1       /* Dump as user of process */
-#define SUID_DUMP_ROOT         2       /* Dump as root */
 
 /* Stack area protections */
 #define EXSTACK_DEFAULT   0    /* Whatever the arch defaults to */
index 78cdf51ff5ba57bb49ee7288601e55c07d648d69..eb8a49d75ab3155bb6910eab585e5dfed9f64dee 100644 (file)
        COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
 
 #define COMPAT_SYSCALL_DEFINEx(x, name, ...)                           \
-       asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
+       asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\
+               __attribute__((alias(__stringify(compat_SyS##name))));  \
        static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
        asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\
        asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
        {                                                               \
                return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \
        }                                                               \
-       SYSCALL_ALIAS(compat_sys##name, compat_SyS##name);              \
        static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 #ifndef compat_user_stack_pointer
index f8d41cb1cbe0a4afb726779f4c0ca05ff9a2a926..1eda33d7cb1089ac91c2b3499d76e47f97051b1a 100644 (file)
@@ -94,6 +94,8 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr,
 }
 extern void gen_pool_destroy(struct gen_pool *);
 extern unsigned long gen_pool_alloc(struct gen_pool *, size_t);
+extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size,
+               dma_addr_t *dma);
 extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
 extern void gen_pool_for_each_chunk(struct gen_pool *,
        void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
index f1c27a71d03c9ee03754f882cd738d90d58ac25b..8e68a64bfe00b8f151300cc240acedb3820d37dd 100644 (file)
@@ -26,8 +26,8 @@
  * extern int initialize_foobar_device(int, int, int) __init;
  *
  * For initialized data:
- * You should insert __initdata between the variable name and equal
- * sign followed by value, e.g.:
+ * You should insert __initdata or __initconst between the variable name
+ * and equal sign followed by value, e.g.:
  *
  * static int init_variable __initdata = 0;
  * static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
@@ -35,8 +35,6 @@
  * Don't forget to initialize data not at file scope, i.e. within a function,
  * as gcc otherwise puts the data into the bss section and not into the init
  * section.
- * 
- * Also note, that this data cannot be "const".
  */
 
 /* These are for everybody (although not all archs will actually
index a5079072da663e6b1e426504c3dfa39438e42127..cf08540d62048db2a222b7ea35e8ccfe9632ece0 100644 (file)
@@ -132,14 +132,14 @@ static __always_inline void jump_label_init(void)
 
 static __always_inline bool static_key_false(struct static_key *key)
 {
-       if (unlikely(atomic_read(&key->enabled)) > 0)
+       if (unlikely(atomic_read(&key->enabled) > 0))
                return true;
        return false;
 }
 
 static __always_inline bool static_key_true(struct static_key *key)
 {
-       if (likely(atomic_read(&key->enabled)) > 0)
+       if (likely(atomic_read(&key->enabled) > 0))
                return true;
        return false;
 }
index 546eb6a76934ba9fa515e81d43893deea0dddfe6..f65ce09784f14b4ec67802b69e032297433b91c0 100644 (file)
@@ -15,5 +15,6 @@
 #define KPF_OWNER_PRIVATE      37
 #define KPF_ARCH               38
 #define KPF_UNCACHED           39
+#define KPF_SOFTDIRTY          40
 
 #endif /* LINUX_KERNEL_PAGE_FLAGS_H */
index f4d8a2f12a33263b63ebc50fc61d8d7b5b3eb6d3..ef959417106222d475fbc01c419cf42db05dcca6 100644 (file)
@@ -361,6 +361,17 @@ static inline void list_splice_tail_init(struct list_head *list,
 #define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)
 
+/**
+ * list_last_entry - get the last element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+       list_entry((ptr)->prev, type, member)
+
 /**
  * list_first_entry_or_null - get the first element from a list
  * @ptr:       the list head to take the element from.
@@ -372,6 +383,22 @@ static inline void list_splice_tail_init(struct list_head *list,
 #define list_first_entry_or_null(ptr, type, member) \
        (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
 
+/**
+ * list_next_entry - get the next element in list
+ * @pos:       the type * to cursor
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_next_entry(pos, member) \
+       list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @pos:       the type * to cursor
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_prev_entry(pos, member) \
+       list_entry((pos)->member.prev, typeof(*(pos)), member)
+
 /**
  * list_for_each       -       iterate over a list
  * @pos:       the &struct list_head to use as a loop cursor.
@@ -416,9 +443,9 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @member:    the name of the list_struct within the struct.
  */
 #define list_for_each_entry(pos, head, member)                         \
-       for (pos = list_entry((head)->next, typeof(*pos), member);      \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (pos = list_first_entry(head, typeof(*pos), member);        \
+            &pos->member != (head);                                    \
+            pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_reverse - iterate backwards over list of given type.
@@ -427,9 +454,9 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @member:    the name of the list_struct within the struct.
  */
 #define list_for_each_entry_reverse(pos, head, member)                 \
-       for (pos = list_entry((head)->prev, typeof(*pos), member);      \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.prev, typeof(*pos), member))
+       for (pos = list_last_entry(head, typeof(*pos), member);         \
+            &pos->member != (head);                                    \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
@@ -452,9 +479,9 @@ static inline void list_splice_tail_init(struct list_head *list,
  * the current position.
  */
 #define list_for_each_entry_continue(pos, head, member)                \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (pos = list_next_entry(pos, member);                        \
+            &pos->member != (head);                                    \
+            pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_continue_reverse - iterate backwards from the given point
@@ -466,9 +493,9 @@ static inline void list_splice_tail_init(struct list_head *list,
  * the current position.
  */
 #define list_for_each_entry_continue_reverse(pos, head, member)                \
-       for (pos = list_entry(pos->member.prev, typeof(*pos), member);  \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.prev, typeof(*pos), member))
+       for (pos = list_prev_entry(pos, member);                        \
+            &pos->member != (head);                                    \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_for_each_entry_from - iterate over list of given type from the current point
@@ -479,8 +506,8 @@ static inline void list_splice_tail_init(struct list_head *list,
  * Iterate over list of given type, continuing from current position.
  */
 #define list_for_each_entry_from(pos, head, member)                    \
-       for (; &pos->member != (head);  \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (; &pos->member != (head);                                  \
+            pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
@@ -490,10 +517,10 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @member:    the name of the list_struct within the struct.
  */
 #define list_for_each_entry_safe(pos, n, head, member)                 \
-       for (pos = list_entry((head)->next, typeof(*pos), member),      \
-               n = list_entry(pos->member.next, typeof(*pos), member); \
+       for (pos = list_first_entry(head, typeof(*pos), member),        \
+               n = list_next_entry(pos, member);                       \
             &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_continue - continue list iteration safe against removal
@@ -506,10 +533,10 @@ static inline void list_splice_tail_init(struct list_head *list,
  * safe against removal of list entry.
  */
 #define list_for_each_entry_safe_continue(pos, n, head, member)                \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member),          \
-               n = list_entry(pos->member.next, typeof(*pos), member);         \
+       for (pos = list_next_entry(pos, member),                                \
+               n = list_next_entry(pos, member);                               \
             &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
@@ -522,9 +549,9 @@ static inline void list_splice_tail_init(struct list_head *list,
  * removal of list entry.
  */
 #define list_for_each_entry_safe_from(pos, n, head, member)                    \
-       for (n = list_entry(pos->member.next, typeof(*pos), member);            \
+       for (n = list_next_entry(pos, member);                                  \
             &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
@@ -537,10 +564,10 @@ static inline void list_splice_tail_init(struct list_head *list,
  * of list entry.
  */
 #define list_for_each_entry_safe_reverse(pos, n, head, member)         \
-       for (pos = list_entry((head)->prev, typeof(*pos), member),      \
-               n = list_entry(pos->member.prev, typeof(*pos), member); \
+       for (pos = list_last_entry(head, typeof(*pos), member),         \
+               n = list_prev_entry(pos, member);                       \
             &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+            pos = n, n = list_prev_entry(n, member))
 
 /**
  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
@@ -555,7 +582,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * completing the current iteration of the loop body.
  */
 #define list_safe_reset_next(pos, n, member)                           \
-       n = list_entry(pos->member.next, typeof(*pos), member)
+       n = list_next_entry(pos, member)
 
 /*
  * Double linked lists with a single pointer list head.
index 31e95acddb4dc3eb76020ea9f1ab09823330d55f..77c60e52939da9f74611e8d3443b04220396ca26 100644 (file)
@@ -35,6 +35,7 @@ struct memblock_type {
 };
 
 struct memblock {
+       bool bottom_up;  /* is bottom up direction? */
        phys_addr_t current_limit;
        struct memblock_type memory;
        struct memblock_type reserved;
@@ -148,6 +149,29 @@ phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
 
 phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
 
+#ifdef CONFIG_MOVABLE_NODE
+/*
+ * Set the allocation direction to bottom-up or top-down.
+ */
+static inline void memblock_set_bottom_up(bool enable)
+{
+       memblock.bottom_up = enable;
+}
+
+/*
+ * Check if the allocation direction is bottom-up or not.
+ * if this is true, that said, memblock will allocate memory
+ * in bottom-up direction.
+ */
+static inline bool memblock_bottom_up(void)
+{
+       return memblock.bottom_up;
+}
+#else
+static inline void memblock_set_bottom_up(bool enable) {}
+static inline bool memblock_bottom_up(void) { return false; }
+#endif
+
 /* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
 #define MEMBLOCK_ALLOC_ANYWHERE        (~(phys_addr_t)0)
 #define MEMBLOCK_ALLOC_ACCESSIBLE      0
index dd38e62b84d2824ecf1e412cdd7fbb908dac675f..4ca3d951fe91c8c90f3f890d37a08d96c85b27f2 100644 (file)
@@ -94,6 +94,8 @@ extern void __online_page_set_limits(struct page *page);
 extern void __online_page_increment_counters(struct page *page);
 extern void __online_page_free(struct page *page);
 
+extern int try_online_node(int nid);
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 extern bool is_pageblock_removable_nolock(struct page *page);
 extern int arch_remove_memory(u64 start, u64 size);
@@ -225,6 +227,11 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
 {
 }
 
+static inline int try_online_node(int nid)
+{
+       return 0;
+}
+
 static inline void lock_memory_hotplug(void) {}
 static inline void unlock_memory_hotplug(void) {}
 
@@ -256,14 +263,12 @@ static inline void remove_memory(int nid, u64 start, u64 size) {}
 
 extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
                void *arg, int (*func)(struct memory_block *, void *));
-extern int mem_online_node(int nid);
 extern int add_memory(int nid, u64 start, u64 size);
 extern int arch_add_memory(int nid, u64 start, u64 size);
 extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
 extern bool is_memblock_offlined(struct memory_block *mem);
 extern void remove_memory(int nid, u64 start, u64 size);
-extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
-                                                               int nr_pages);
+extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn);
 extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
 extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
                                          unsigned long pnum);
index ea4d2495c6464bb2a5789f2566358461cca31330..9fe426b30a418e335485a7aee045883c974f15de 100644 (file)
@@ -169,7 +169,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
 extern int mpol_parse_str(char *str, struct mempolicy **mpol);
 #endif
 
-extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol);
+extern void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol);
 
 /* Check if a vma is migratable */
 static inline int vma_migratable(struct vm_area_struct *vma)
@@ -307,9 +307,8 @@ static inline int mpol_parse_str(char *str, struct mempolicy **mpol)
 }
 #endif
 
-static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+static inline void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 {
-       return 0;
 }
 
 static inline int mpol_misplaced(struct page *page, struct vm_area_struct *vma,
index 378ae8a04c6a081265b22722c84d2631bcd82b58..2d0c9071bcfb795a4f34cdc44b1e88abae394c5e 100644 (file)
@@ -51,6 +51,7 @@ struct sec_pmic_dev {
        int ono;
        int type;
        bool wakeup;
+       bool wtsr_smpl;
 };
 
 int sec_irq_init(struct sec_pmic_dev *sec_pmic);
index 71597e20cddb54d1aaa45474f82120c4d1f1e868..94b7cd6d889185f9df10b611099bf06038365b83 100644 (file)
@@ -62,6 +62,11 @@ enum sec_rtc_reg {
 /* RTC Update Register1 */
 #define RTC_UDR_SHIFT          0
 #define RTC_UDR_MASK           (1 << RTC_UDR_SHIFT)
+#define RTC_TCON_SHIFT         1
+#define RTC_TCON_MASK          (1 << RTC_TCON_SHIFT)
+#define RTC_TIME_EN_SHIFT      3
+#define RTC_TIME_EN_MASK       (1 << RTC_TIME_EN_SHIFT)
+
 /* RTC Hour register */
 #define HOUR_PM_SHIFT          6
 #define HOUR_PM_MASK           (1 << HOUR_PM_SHIFT)
@@ -69,6 +74,12 @@ enum sec_rtc_reg {
 #define ALARM_ENABLE_SHIFT     7
 #define ALARM_ENABLE_MASK      (1 << ALARM_ENABLE_SHIFT)
 
+#define SMPL_ENABLE_SHIFT      7
+#define SMPL_ENABLE_MASK       (1 << SMPL_ENABLE_SHIFT)
+
+#define WTSR_ENABLE_SHIFT      6
+#define WTSR_ENABLE_MASK       (1 << WTSR_ENABLE_SHIFT)
+
 enum {
        RTC_SEC = 0,
        RTC_MIN,
index 8aa4006b9636e11dbcb4e32e988f43c30c865396..42a35d94b82caaf6c74e86befb923650440970ea 100644 (file)
@@ -50,6 +50,10 @@ extern int sysctl_legacy_va_layout;
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 
+#ifndef __pa_symbol
+#define __pa_symbol(x)  __pa(RELOC_HIDE((unsigned long)(x), 0))
+#endif
+
 extern unsigned long sysctl_user_reserve_kbytes;
 extern unsigned long sysctl_admin_reserve_kbytes;
 
index 92dc257251e45a04b75445d049922688cac7fbe9..7f7f8dae4b1deec32eb1079428f4b13b87dd25c7 100644 (file)
@@ -87,4 +87,6 @@ calc_vm_flag_bits(unsigned long flags)
               _calc_vm_trans(flags, MAP_DENYWRITE,  VM_DENYWRITE ) |
               _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    );
 }
+
+unsigned long vm_commit_limit(void);
 #endif /* _LINUX_MMAN_H */
index 391af8d11cceea2f306f460ec137d75f0ea236c9..e21f9d44307f0004baf0146b4d02a20de6a96466 100644 (file)
@@ -6,9 +6,9 @@
 
 /* one msg_msg structure for each message */
 struct msg_msg {
-       struct list_head m_list; 
-       long  m_type;          
-       int m_ts;           /* message text size */
+       struct list_head m_list;
+       long m_type;
+       size_t m_ts;            /* message text size */
        struct msg_msgseg* next;
        void *security;
        /* the actual message follows immediately */
index da60007075b509b864d386b3d9092c77aec97c64..4cd62677feb9eaf8f9a4647231663a8d7a42f986 100644 (file)
@@ -82,6 +82,11 @@ static inline void oom_killer_enable(void)
        oom_killer_disabled = false;
 }
 
+static inline bool oom_gfp_allowed(gfp_t gfp_mask)
+{
+       return (gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY);
+}
+
 extern struct task_struct *find_lock_task_mm(struct task_struct *p);
 
 /* sysctls */
diff --git a/include/linux/platform_data/lm3630_bl.h b/include/linux/platform_data/lm3630_bl.h
deleted file mode 100644 (file)
index 9176dd3..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-* Simple driver for Texas Instruments LM3630 LED Flash driver chip
-* Copyright (C) 2012 Texas Instruments
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*
-*/
-
-#ifndef __LINUX_LM3630_H
-#define __LINUX_LM3630_H
-
-#define LM3630_NAME "lm3630_bl"
-
-enum lm3630_pwm_ctrl {
-       PWM_CTRL_DISABLE = 0,
-       PWM_CTRL_BANK_A,
-       PWM_CTRL_BANK_B,
-       PWM_CTRL_BANK_ALL,
-};
-
-enum lm3630_pwm_active {
-       PWM_ACTIVE_HIGH = 0,
-       PWM_ACTIVE_LOW,
-};
-
-enum lm3630_bank_a_ctrl {
-       BANK_A_CTRL_DISABLE = 0x0,
-       BANK_A_CTRL_LED1 = 0x4,
-       BANK_A_CTRL_LED2 = 0x1,
-       BANK_A_CTRL_ALL = 0x5,
-};
-
-enum lm3630_bank_b_ctrl {
-       BANK_B_CTRL_DISABLE = 0,
-       BANK_B_CTRL_LED2,
-};
-
-struct lm3630_platform_data {
-
-       /* maximum brightness */
-       int max_brt_led1;
-       int max_brt_led2;
-
-       /* initial on brightness */
-       int init_brt_led1;
-       int init_brt_led2;
-       enum lm3630_pwm_ctrl pwm_ctrl;
-       enum lm3630_pwm_active pwm_active;
-       enum lm3630_bank_a_ctrl bank_a_ctrl;
-       enum lm3630_bank_b_ctrl bank_b_ctrl;
-       unsigned int pwm_period;
-       void (*pwm_set_intensity) (int brightness, int max_brightness);
-};
-
-#endif /* __LINUX_LM3630_H */
diff --git a/include/linux/platform_data/lm3630a_bl.h b/include/linux/platform_data/lm3630a_bl.h
new file mode 100644 (file)
index 0000000..7538e38
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+* Simple driver for Texas Instruments LM3630A LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+
+#ifndef __LINUX_LM3630A_H
+#define __LINUX_LM3630A_H
+
+#define LM3630A_NAME "lm3630a_bl"
+
+enum lm3630a_pwm_ctrl {
+       LM3630A_PWM_DISABLE = 0x00,
+       LM3630A_PWM_BANK_A,
+       LM3630A_PWM_BANK_B,
+       LM3630A_PWM_BANK_ALL,
+       LM3630A_PWM_BANK_A_ACT_LOW = 0x05,
+       LM3630A_PWM_BANK_B_ACT_LOW,
+       LM3630A_PWM_BANK_ALL_ACT_LOW,
+};
+
+enum lm3630a_leda_ctrl {
+       LM3630A_LEDA_DISABLE = 0x00,
+       LM3630A_LEDA_ENABLE = 0x04,
+       LM3630A_LEDA_ENABLE_LINEAR = 0x14,
+};
+
+enum lm3630a_ledb_ctrl {
+       LM3630A_LEDB_DISABLE = 0x00,
+       LM3630A_LEDB_ON_A = 0x01,
+       LM3630A_LEDB_ENABLE = 0x02,
+       LM3630A_LEDB_ENABLE_LINEAR = 0x0A,
+};
+
+#define LM3630A_MAX_BRIGHTNESS 255
+/*
+ *@leda_init_brt : led a init brightness. 4~255
+ *@leda_max_brt  : led a max brightness.  4~255
+ *@leda_ctrl     : led a disable, enable linear, enable exponential
+ *@ledb_init_brt : led b init brightness. 4~255
+ *@ledb_max_brt  : led b max brightness.  4~255
+ *@ledb_ctrl     : led b disable, enable linear, enable exponential
+ *@pwm_period    : pwm period
+ *@pwm_ctrl      : pwm disable, bank a or b, active high or low
+ */
+struct lm3630a_platform_data {
+
+       /* led a config.  */
+       int leda_init_brt;
+       int leda_max_brt;
+       enum lm3630a_leda_ctrl leda_ctrl;
+       /* led b config. */
+       int ledb_init_brt;
+       int ledb_max_brt;
+       enum lm3630a_ledb_ctrl ledb_ctrl;
+       /* pwm config. */
+       unsigned int pwm_period;
+       enum lm3630a_pwm_ctrl pwm_ctrl;
+};
+
+#endif /* __LINUX_LM3630A_H */
index ea3200527dd302c6028d5f23d39f53415e89870c..1b2ba24e4e03bf98ac35d990c634e1a08ae19e15 100644 (file)
 #define LP8553_PWM_CONFIG      LP8550_PWM_CONFIG
 #define LP8553_I2C_CONFIG      LP8550_I2C_CONFIG
 
+/* CONFIG register - LP8555 */
+#define LP8555_PWM_STANDBY     BIT(7)
+#define LP8555_PWM_FILTER      BIT(6)
+#define LP8555_RELOAD_EPROM    BIT(3)  /* use it if EPROMs should be reset
+                                          when the backlight turns on */
+#define LP8555_OFF_OPENLEDS    BIT(2)
+#define LP8555_PWM_CONFIG      LP8555_PWM_ONLY
+#define LP8555_I2C_CONFIG      LP8555_I2C_ONLY
+#define LP8555_COMB1_CONFIG    LP8555_COMBINED1
+#define LP8555_COMB2_CONFIG    LP8555_COMBINED2
+
 /* DEVICE CONTROL register - LP8556 */
 #define LP8556_PWM_CONFIG      (LP8556_PWM_ONLY << BRT_MODE_SHFT)
 #define LP8556_COMB1_CONFIG    (LP8556_COMBINED1 << BRT_MODE_SHFT)
@@ -65,6 +76,7 @@ enum lp855x_chip_id {
        LP8551,
        LP8552,
        LP8553,
+       LP8555,
        LP8556,
        LP8557,
 };
@@ -89,6 +101,13 @@ enum lp8553_brighntess_source {
        LP8553_I2C_ONLY = LP8550_I2C_ONLY,
 };
 
+enum lp8555_brightness_source {
+       LP8555_PWM_ONLY,
+       LP8555_I2C_ONLY,
+       LP8555_COMBINED1,       /* Brightness register with shaped PWM */
+       LP8555_COMBINED2,       /* PWM with shaped brightness register */
+};
+
 enum lp8556_brightness_source {
        LP8556_PWM_ONLY,
        LP8556_COMBINED1,       /* pwm + i2c before the shaper block */
index aa870a4ddf5428bd120d464f0ffb304ec27b868f..57e75ae9910f7584f47c523ae1671ce916e9ed67 100644 (file)
@@ -85,6 +85,11 @@ static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
        *rb_link = node;
 }
 
+#define rb_entry_safe(ptr, type, member) \
+       ({ typeof(ptr) ____ptr = (ptr); \
+          ____ptr ? rb_entry(____ptr, type, member) : NULL; \
+       })
+
 /**
  * rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of
  * given type safe against removal of rb_node entry
@@ -95,12 +100,9 @@ static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
  * @field:     the name of the rb_node field within 'type'.
  */
 #define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
-       for (pos = rb_entry(rb_first_postorder(root), typeof(*pos), field),\
-               n = rb_entry(rb_next_postorder(&pos->field), \
-                       typeof(*pos), field); \
-            &pos->field; \
-            pos = n, \
-               n = rb_entry(rb_next_postorder(&pos->field), \
-                       typeof(*pos), field))
+       for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
+            pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
+                       typeof(*pos), field); 1; }); \
+            pos = n)
 
 #endif /* _LINUX_RBTREE_H */
index 045b0d2278463583e90a57d7e80d4257ecea1b06..f7efc86046522c2722501f5967d65983162fa78e 100644 (file)
@@ -323,6 +323,10 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
 extern void set_dumpable(struct mm_struct *mm, int value);
 extern int get_dumpable(struct mm_struct *mm);
 
+#define SUID_DUMP_DISABLE      0       /* No setuid dumping */
+#define SUID_DUMP_USER         1       /* Dump as user of process */
+#define SUID_DUMP_ROOT         2       /* Dump as root */
+
 /* mm flags */
 /* dumpable bits */
 #define MMF_DUMPABLE      0  /* core dump is permitted */
@@ -1062,15 +1066,6 @@ struct task_struct {
        struct hlist_head preempt_notifiers;
 #endif
 
-       /*
-        * fpu_counter contains the number of consecutive context switches
-        * that the FPU is used. If this is over a threshold, the lazy fpu
-        * saving becomes unlazy to save the trap. This is an unsigned char
-        * so that after 256 times the counter wraps and the behavior turns
-        * lazy again; this to deal with bursty apps that only use FPU for
-        * a short time
-        */
-       unsigned char fpu_counter;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
        unsigned int btrace_seq;
 #endif
index 7fac04e7ff6eac91f4d8a37d30486892e1dac141..c27f846f6b71ae10cc5a98de630f55e898b2c8e5 100644 (file)
@@ -184,7 +184,8 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 
 #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
 #define __SYSCALL_DEFINEx(x, name, ...)                                        \
-       asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));      \
+       asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
+               __attribute__((alias(__stringify(SyS##name))));         \
        static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));  \
        asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));      \
        asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))       \
@@ -194,7 +195,6 @@ extern struct trace_event_functions exit_syscall_print_funcs;
                __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));       \
                return ret;                                             \
        }                                                               \
-       SYSCALL_ALIAS(sys##name, SyS##name);                            \
        static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 asmlinkage long sys_time(time_t __user *tloc);
index 1855f0a22add848202b693a16d103072a8f3487a..c557c6d096def9a93bb5b00af4df87166539e048 100644 (file)
@@ -39,6 +39,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                PAGEOUTRUN, ALLOCSTALL, PGROTATED,
 #ifdef CONFIG_NUMA_BALANCING
                NUMA_PTE_UPDATES,
+               NUMA_HUGE_PTE_UPDATES,
                NUMA_HINT_FAULTS,
                NUMA_HINT_FAULTS_LOCAL,
                NUMA_PAGE_MIGRATE,
index 021b8a319b9e2cf7f0f60a5f6fedcfe3367f8016..fc0e4320aa6d50d0e5f966e3f8b649506d461ac7 100644 (file)
@@ -97,7 +97,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
 int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason);
 int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
                                  enum wb_reason reason);
-void sync_inodes_sb(struct super_block *);
+void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this);
 void wakeup_flusher_threads(long nr_pages, enum wb_reason reason);
 void inode_wait_for_writeback(struct inode *inode);
 
index d0c613476620fa9da3f60220557dee19eb725c86..aece1346ceb741bf11dd0d70215a4f91e9eeba3c 100644 (file)
@@ -267,14 +267,12 @@ DEFINE_EVENT_PRINT(mm_page, mm_page_pcpu_drain,
 TRACE_EVENT(mm_page_alloc_extfrag,
 
        TP_PROTO(struct page *page,
-                       int alloc_order, int fallback_order,
-                       int alloc_migratetype, int fallback_migratetype,
-                       int change_ownership),
+               int alloc_order, int fallback_order,
+               int alloc_migratetype, int fallback_migratetype, int new_migratetype),
 
        TP_ARGS(page,
                alloc_order, fallback_order,
-               alloc_migratetype, fallback_migratetype,
-               change_ownership),
+               alloc_migratetype, fallback_migratetype, new_migratetype),
 
        TP_STRUCT__entry(
                __field(        struct page *,  page                    )
@@ -291,7 +289,7 @@ TRACE_EVENT(mm_page_alloc_extfrag,
                __entry->fallback_order         = fallback_order;
                __entry->alloc_migratetype      = alloc_migratetype;
                __entry->fallback_migratetype   = fallback_migratetype;
-               __entry->change_ownership       = change_ownership;
+               __entry->change_ownership       = (new_migratetype == alloc_migratetype);
        ),
 
        TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d",
index 464ea82e10dbf1f1a519b75c52f9e129a5a715e0..c7bbbe794e65cdd0a41c7235bcee6e9718970876 100644 (file)
@@ -287,11 +287,11 @@ TRACE_EVENT(writeback_queue_io,
                __field(int,            reason)
        ),
        TP_fast_assign(
-               unsigned long *older_than_this = work->older_than_this;
+               unsigned long older_than_this = work->older_than_this;
                strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
-               __entry->older  = older_than_this ?  *older_than_this : 0;
+               __entry->older  = older_than_this;
                __entry->age    = older_than_this ?
-                                 (jiffies - *older_than_this) * 1000 / HZ : -1;
+                                 (jiffies - older_than_this) * 1000 / HZ : -1;
                __entry->moved  = moved;
                __entry->reason = work->reason;
        ),
index a1331ce5044584eb1266546ae9b79d1e87e26b16..1e1ea6e6e7a55b63d9b492b8676e7aaa3f17e1ff 100644 (file)
@@ -86,7 +86,7 @@
 #define        EHOSTUNREACH    113     /* No route to host */
 #define        EALREADY        114     /* Operation already in progress */
 #define        EINPROGRESS     115     /* Operation now in progress */
-#define        ESTALE          116     /* Stale NFS file handle */
+#define        ESTALE          116     /* Stale file handle */
 #define        EUCLEAN         117     /* Structure needs cleaning */
 #define        ENOTNAM         118     /* Not a XENIX named type file */
 #define        ENAVAIL         119     /* No XENIX semaphores available */
index bc8911fab28e3e541d201dfe1296b933a494837b..5496f307988ee44603ead02db2b2c5caa48511bd 100644 (file)
@@ -118,7 +118,6 @@ config HAVE_KERNEL_LZ4
 choice
        prompt "Kernel compression mode"
        default KERNEL_GZIP
-       depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4
        help
          The linux kernel is a kind of self-extracting executable.
          Several compression algorithms are available, which differ
@@ -137,6 +136,13 @@ choice
 
          If in doubt, select 'gzip'
 
+config KERNEL_UNCOMPRESSED
+       bool "No compression"
+       help
+         No compression at all. The kernel is huge but the compression and
+         decompression times are zero.
+         This is usually not what you want.
+
 config KERNEL_GZIP
        bool "Gzip"
        depends on HAVE_KERNEL_GZIP
index a51cddc2ff8c184e7a7034585190a9fad8ad270b..8e5addc458742a3cccd8609e79e5265081383345 100644 (file)
@@ -197,6 +197,8 @@ done:
  *        is a zero-filled hex representation of the 1-based partition number.
  *     7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
  *        a partition with a known unique id.
+ *     8) <major>:<minor> major and minor number of the device separated by
+ *        a colon.
  *
  *     If name doesn't have fall into the categories above, we return (0,0).
  *     block_class is used to check if something is a disk name. If the disk
index 6be2879cca66971859b1c51ff80451616ab13975..7c098ac9068a582af317596908390ad74011040e 100644 (file)
@@ -57,6 +57,11 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
  *     cramfs
  *     squashfs
  *     gzip
+ *     bzip2
+ *     lzma
+ *     xz
+ *     lzo
+ *     lz4
  */
 static int __init
 identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
@@ -342,6 +347,13 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)
        int result;
        crd_infd = in_fd;
        crd_outfd = out_fd;
+
+       if (!deco) {
+               pr_emerg("Invalid ramdisk decompression routine.  "
+                        "Select appropriate config option.\n");
+               panic("Could not decompress initial ramdisk image.");
+       }
+
        result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);
        if (decompress_error)
                result = 1;
index 379090fadac9a1652aa9f095db2bf6ef49ddc763..67ee8ef0a6691422f62529164fe3e25c0fb492d9 100644 (file)
@@ -124,7 +124,6 @@ EXPORT_SYMBOL(system_state);
 extern void time_init(void);
 /* Default late time init is NULL. archs can override this later. */
 void (*__initdata late_time_init)(void);
-extern void softirq_init(void);
 
 /* Untouched command line saved by arch-specific code. */
 char __initdata boot_command_line[COMMAND_LINE_SIZE];
@@ -811,10 +810,26 @@ static int run_init_process(const char *init_filename)
                (const char __user *const __user *)envp_init);
 }
 
+static int try_to_run_init_process(const char *init_filename)
+{
+       int ret;
+
+       ret = run_init_process(init_filename);
+
+       if (ret && ret != -ENOENT) {
+               pr_err("Starting init: %s exists but couldn't execute it (error %d)\n",
+                      init_filename, ret);
+       }
+
+       return ret;
+}
+
 static noinline void __init kernel_init_freeable(void);
 
 static int __ref kernel_init(void *unused)
 {
+       int ret;
+
        kernel_init_freeable();
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
@@ -826,9 +841,11 @@ static int __ref kernel_init(void *unused)
        flush_delayed_fput();
 
        if (ramdisk_execute_command) {
-               if (!run_init_process(ramdisk_execute_command))
+               ret = run_init_process(ramdisk_execute_command);
+               if (!ret)
                        return 0;
-               pr_err("Failed to execute %s\n", ramdisk_execute_command);
+               pr_err("Failed to execute %s (error %d)\n",
+                      ramdisk_execute_command, ret);
        }
 
        /*
@@ -838,18 +855,19 @@ static int __ref kernel_init(void *unused)
         * trying to recover a really broken machine.
         */
        if (execute_command) {
-               if (!run_init_process(execute_command))
+               ret = run_init_process(execute_command);
+               if (!ret)
                        return 0;
-               pr_err("Failed to execute %s.  Attempting defaults...\n",
-                       execute_command);
+               pr_err("Failed to execute %s (error %d).  Attempting defaults...\n",
+                       execute_command, ret);
        }
-       if (!run_init_process("/sbin/init") ||
-           !run_init_process("/etc/init") ||
-           !run_init_process("/bin/init") ||
-           !run_init_process("/bin/sh"))
+       if (!try_to_run_init_process("/sbin/init") ||
+           !try_to_run_init_process("/etc/init") ||
+           !try_to_run_init_process("/bin/init") ||
+           !try_to_run_init_process("/bin/sh"))
                return 0;
 
-       panic("No init found.  Try passing init= option to kernel. "
+       panic("No working init found.  Try passing init= option to kernel. "
              "See Linux Documentation/init.txt for guidance.");
 }
 
index 491e71f2a1b862a72e78a54e7b16e08812a13f3d..7e7095974d54a10e175dd06504cb8dc6ac73adcb 100644 (file)
@@ -41,15 +41,15 @@ struct msg_msgseg {
        /* the next part of the message follows immediately */
 };
 
-#define DATALEN_MSG    (int)(PAGE_SIZE-sizeof(struct msg_msg))
-#define DATALEN_SEG    (int)(PAGE_SIZE-sizeof(struct msg_msgseg))
+#define DATALEN_MSG    ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
+#define DATALEN_SEG    ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 
 
-static struct msg_msg *alloc_msg(int len)
+static struct msg_msg *alloc_msg(size_t len)
 {
        struct msg_msg *msg;
        struct msg_msgseg **pseg;
-       int alen;
+       size_t alen;
 
        alen = min(len, DATALEN_MSG);
        msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
@@ -80,12 +80,12 @@ out_err:
        return NULL;
 }
 
-struct msg_msg *load_msg(const void __user *src, int len)
+struct msg_msg *load_msg(const void __user *src, size_t len)
 {
        struct msg_msg *msg;
        struct msg_msgseg *seg;
        int err = -EFAULT;
-       int alen;
+       size_t alen;
 
        msg = alloc_msg(len);
        if (msg == NULL)
@@ -117,8 +117,8 @@ out_err:
 struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
 {
        struct msg_msgseg *dst_pseg, *src_pseg;
-       int len = src->m_ts;
-       int alen;
+       size_t len = src->m_ts;
+       size_t alen;
 
        BUG_ON(dst == NULL);
        if (src->m_ts > dst->m_ts)
@@ -147,9 +147,9 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
        return ERR_PTR(-ENOSYS);
 }
 #endif
-int store_msg(void __user *dest, struct msg_msg *msg, int len)
+int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
 {
-       int alen;
+       size_t alen;
        struct msg_msgseg *seg;
 
        alen = min(len, DATALEN_MSG);
index 7684f41bce76a9b430f04b7e4e77810b48798a42..3ae17a4ace5b9ba242fd1aa42543d64145e5cb7f 100644 (file)
@@ -90,10 +90,8 @@ static int ipc_memory_callback(struct notifier_block *self,
                 * In order not to keep the lock on the hotplug memory chain
                 * for too long, queue a work item that will, when waken up,
                 * activate the ipcns notification chain.
-                * No need to keep several ipc work items on the queue.
                 */
-               if (!work_pending(&ipc_memory_wq))
-                       schedule_work(&ipc_memory_wq);
+               schedule_work(&ipc_memory_wq);
                break;
        case MEM_GOING_ONLINE:
        case MEM_GOING_OFFLINE:
index f2f5036f2eeda9794bc545ac8045db3c56f7d425..59d78aa949874aff138845ce13fb55c764205f9d 100644 (file)
@@ -148,9 +148,9 @@ int ipc_parse_version (int *cmd);
 #endif
 
 extern void free_msg(struct msg_msg *msg);
-extern struct msg_msg *load_msg(const void __user *src, int len);
+extern struct msg_msg *load_msg(const void __user *src, size_t len);
 extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
-extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
+extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
 
 extern void recompute_msgmni(struct ipc_namespace *);
 
index 63aa50d7ce1efa16f9c29faa97f734f8c5db5d34..973d034acf844b25c1f1d35cd66dd7ff17e2c31d 100644 (file)
@@ -437,11 +437,6 @@ int cpu_up(unsigned int cpu)
 {
        int err = 0;
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-       int nid;
-       pg_data_t       *pgdat;
-#endif
-
        if (!cpu_possible(cpu)) {
                printk(KERN_ERR "can't online cpu %d because it is not "
                        "configured as may-hotadd at boot time\n", cpu);
@@ -452,27 +447,9 @@ int cpu_up(unsigned int cpu)
                return -EINVAL;
        }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-       nid = cpu_to_node(cpu);
-       if (!node_online(nid)) {
-               err = mem_online_node(nid);
-               if (err)
-                       return err;
-       }
-
-       pgdat = NODE_DATA(nid);
-       if (!pgdat) {
-               printk(KERN_ERR
-                       "Can't online cpu %d due to NULL pgdat\n", cpu);
-               return -ENOMEM;
-       }
-
-       if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
-               mutex_lock(&zonelists_mutex);
-               build_all_zonelists(NULL, NULL);
-               mutex_unlock(&zonelists_mutex);
-       }
-#endif
+       err = try_online_node(cpu_to_node(cpu));
+       if (err)
+               return err;
 
        cpu_maps_update_begin();
 
index d473988c1d0bc7505db5cbd17f637787bcdd3d1c..54996b71e66d82817cc16ed1963c1490c7dd4db4 100644 (file)
@@ -108,12 +108,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
        struct timespec ts;
        cputime_t utime, stime, stimescaled, utimescaled;
 
-       /* Though tsk->delays accessed later, early exit avoids
-        * unnecessary returning of other data
-        */
-       if (!tsk->delays)
-               goto done;
-
        tmp = (s64)d->cpu_run_real_total;
        task_cputime(tsk, &utime, &stime);
        cputime_to_timespec(utime + stime, &ts);
@@ -158,7 +152,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
        d->freepages_count += tsk->delays->freepages_count;
        spin_unlock_irqrestore(&tsk->delays->lock, flags);
 
-done:
        return 0;
 }
 
index 8c875ef6e120920c5fad9c1c70caf20d418bb7aa..d724e7757cd1ec2df7a9c2ac9be1b0c23f6e4e71 100644 (file)
@@ -2234,9 +2234,6 @@ static void __perf_event_sync_stat(struct perf_event *event,
        perf_event_update_userpage(next_event);
 }
 
-#define list_next_entry(pos, member) \
-       list_entry(pos->member.next, typeof(*pos), member)
-
 static void perf_event_sync_stat(struct perf_event_context *ctx,
                                   struct perf_event_context *next_ctx)
 {
index d4da55d1fb65f1a136a6358cf9021265bb483c13..d04ce8ac4399260c8e127bd800a5a12dc91f5044 100644 (file)
@@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
        larger and run slower. Also be sure to exclude files from profiling
        which are not linked to the kernel image to prevent linker errors.
 
+choice
+       prompt "Specify GCOV format"
+       depends on GCOV_KERNEL
+       default GCOV_FORMAT_AUTODETECT
+       ---help---
+       The gcov format is usually determined by the GCC version, but there are
+       exceptions where format changes are integrated in lower-version GCCs.
+       In such a case use this option to adjust the format used in the kernel
+       accordingly.
+
+       If unsure, choose "Autodetect".
+
+config GCOV_FORMAT_AUTODETECT
+       bool "Autodetect"
+       ---help---
+       Select this option to use the format that corresponds to your GCC
+       version.
+
+config GCOV_FORMAT_3_4
+       bool "GCC 3.4 format"
+       ---help---
+       Select this option to use the format defined by GCC 3.4.
+
+config GCOV_FORMAT_4_7
+       bool "GCC 4.7 format"
+       ---help---
+       Select this option to use the format defined by GCC 4.7.
+
+endchoice
+
 endmenu
index e97ca59e2520dce3a3c0d7b2460d444e1b7591c0..52aa7e8de92705c02c061c3ecd3087cb1061b4f8 100644 (file)
@@ -1,3 +1,33 @@
 ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
-obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
+# if-lt
+# Usage VAR := $(call if-lt, $(a), $(b))
+# Returns 1 if (a < b)
+if-lt = $(shell [ $(1) -lt $(2) ] && echo 1)
+
+ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
+  cc-ver := 0304
+else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
+  cc-ver := 0407
+else
+# Use cc-version if available, otherwise set 0
+#
+# scripts/Kbuild.include, which contains cc-version function, is not included
+# during make clean "make -f scripts/Makefile.clean obj=kernel/gcov"
+# Meaning cc-ver is empty causing if-lt test to fail with
+# "/bin/sh: line 0: [: -lt: unary operator expected" error mesage.
+# This has no affect on the clean phase, but the error message could be
+# confusing/annoying. So this dummy workaround sets cc-ver to zero if cc-version
+# is not available. We can probably move if-lt to Kbuild.include, so it's also
+# not defined during clean or to include Kbuild.include in
+# scripts/Makefile.clean. But the following workaround seems least invasive.
+  cc-ver := $(if $(call cc-version),$(call cc-version),0)
+endif
+
+obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
+
+ifeq ($(call if-lt, $(cc-ver), 0407),1)
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
+else
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
+endif
index 9b22d03cc581c798b5ed9b69e564265843429ce6..f45b75b713c0eeff3564cfacb4f0881037bbfc75 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mutex.h>
 #include "gcov.h"
 
-static struct gcov_info *gcov_info_head;
 static int gcov_events_enabled;
 static DEFINE_MUTEX(gcov_lock);
 
@@ -34,7 +33,7 @@ void __gcov_init(struct gcov_info *info)
 
        mutex_lock(&gcov_lock);
        if (gcov_version == 0) {
-               gcov_version = info->version;
+               gcov_version = gcov_info_version(info);
                /*
                 * Printing gcc's version magic may prove useful for debugging
                 * incompatibility reports.
@@ -45,8 +44,7 @@ void __gcov_init(struct gcov_info *info)
         * Add new profiling data structure to list and inform event
         * listener.
         */
-       info->next = gcov_info_head;
-       gcov_info_head = info;
+       gcov_info_link(info);
        if (gcov_events_enabled)
                gcov_event(GCOV_ADD, info);
        mutex_unlock(&gcov_lock);
@@ -81,6 +79,12 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_delta);
 
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
@@ -91,13 +95,15 @@ EXPORT_SYMBOL(__gcov_merge_delta);
  */
 void gcov_enable_events(void)
 {
-       struct gcov_info *info;
+       struct gcov_info *info = NULL;
 
        mutex_lock(&gcov_lock);
        gcov_events_enabled = 1;
+
        /* Perform event callback for previously registered entries. */
-       for (info = gcov_info_head; info; info = info->next)
+       while ((info = gcov_info_next(info)))
                gcov_event(GCOV_ADD, info);
+
        mutex_unlock(&gcov_lock);
 }
 
@@ -112,25 +118,23 @@ static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
                                void *data)
 {
        struct module *mod = data;
-       struct gcov_info *info;
-       struct gcov_info *prev;
+       struct gcov_info *info = NULL;
+       struct gcov_info *prev = NULL;
 
        if (event != MODULE_STATE_GOING)
                return NOTIFY_OK;
        mutex_lock(&gcov_lock);
-       prev = NULL;
+
        /* Remove entries located in module from linked list. */
-       for (info = gcov_info_head; info; info = info->next) {
+       while ((info = gcov_info_next(info))) {
                if (within(info, mod->module_core, mod->core_size)) {
-                       if (prev)
-                               prev->next = info->next;
-                       else
-                               gcov_info_head = info->next;
+                       gcov_info_unlink(prev, info);
                        if (gcov_events_enabled)
                                gcov_event(GCOV_REMOVE, info);
                } else
                        prev = info;
        }
+
        mutex_unlock(&gcov_lock);
 
        return NOTIFY_OK;
index 7a7d2ee96d42c477289c34c4de79647285958319..15ff01a7637912776f16f534e64d9e3f0d002afe 100644 (file)
@@ -75,7 +75,7 @@ static int __init gcov_persist_setup(char *str)
        unsigned long val;
 
        if (kstrtoul(str, 0, &val)) {
-               pr_warning("invalid gcov_persist parameter '%s'\n", str);
+               pr_warn("invalid gcov_persist parameter '%s'\n", str);
                return 0;
        }
        gcov_persist = val;
@@ -242,7 +242,7 @@ static struct gcov_node *get_node_by_name(const char *name)
 
        list_for_each_entry(node, &all_head, all) {
                info = get_node_info(node);
-               if (info && (strcmp(info->filename, name) == 0))
+               if (info && (strcmp(gcov_info_filename(info), name) == 0))
                        return node;
        }
 
@@ -279,7 +279,7 @@ static ssize_t gcov_seq_write(struct file *file, const char __user *addr,
        seq = file->private_data;
        info = gcov_iter_get_info(seq->private);
        mutex_lock(&node_lock);
-       node = get_node_by_name(info->filename);
+       node = get_node_by_name(gcov_info_filename(info));
        if (node) {
                /* Reset counts or remove node for unloaded modules. */
                if (node->num_loaded == 0)
@@ -365,7 +365,7 @@ static const char *deskew(const char *basename)
  */
 static void add_links(struct gcov_node *node, struct dentry *parent)
 {
-       char *basename;
+       const char *basename;
        char *target;
        int num;
        int i;
@@ -376,14 +376,14 @@ static void add_links(struct gcov_node *node, struct dentry *parent)
        if (!node->links)
                return;
        for (i = 0; i < num; i++) {
-               target = get_link_target(get_node_info(node)->filename,
-                                        &gcov_link[i]);
+               target = get_link_target(
+                               gcov_info_filename(get_node_info(node)),
+                               &gcov_link[i]);
                if (!target)
                        goto out_err;
-               basename = strrchr(target, '/');
-               if (!basename)
+               basename = kbasename(target);
+               if (basename == target)
                        goto out_err;
-               basename++;
                node->links[i] = debugfs_create_symlink(deskew(basename),
                                                        parent, target);
                if (!node->links[i])
@@ -450,7 +450,7 @@ static struct gcov_node *new_node(struct gcov_node *parent,
        } else
                node->dentry = debugfs_create_dir(node->name, parent->dentry);
        if (!node->dentry) {
-               pr_warning("could not create file\n");
+               pr_warn("could not create file\n");
                kfree(node);
                return NULL;
        }
@@ -463,7 +463,7 @@ static struct gcov_node *new_node(struct gcov_node *parent,
 
 err_nomem:
        kfree(node);
-       pr_warning("out of memory\n");
+       pr_warn("out of memory\n");
        return NULL;
 }
 
@@ -576,7 +576,7 @@ static void add_node(struct gcov_info *info)
        struct gcov_node *parent;
        struct gcov_node *node;
 
-       filename = kstrdup(info->filename, GFP_KERNEL);
+       filename = kstrdup(gcov_info_filename(info), GFP_KERNEL);
        if (!filename)
                return;
        parent = &root_node;
@@ -630,8 +630,8 @@ static void add_info(struct gcov_node *node, struct gcov_info *info)
         */
        loaded_info = kcalloc(num + 1, sizeof(struct gcov_info *), GFP_KERNEL);
        if (!loaded_info) {
-               pr_warning("could not add '%s' (out of memory)\n",
-                          info->filename);
+               pr_warn("could not add '%s' (out of memory)\n",
+                       gcov_info_filename(info));
                return;
        }
        memcpy(loaded_info, node->loaded_info,
@@ -644,8 +644,9 @@ static void add_info(struct gcov_node *node, struct gcov_info *info)
                 * data set replaces the copy of the last one.
                 */
                if (!gcov_info_is_compatible(node->unloaded_info, info)) {
-                       pr_warning("discarding saved data for %s "
-                                  "(incompatible version)\n", info->filename);
+                       pr_warn("discarding saved data for %s "
+                               "(incompatible version)\n",
+                               gcov_info_filename(info));
                        gcov_info_free(node->unloaded_info);
                        node->unloaded_info = NULL;
                }
@@ -655,8 +656,8 @@ static void add_info(struct gcov_node *node, struct gcov_info *info)
                 * The initial one takes precedence.
                 */
                if (!gcov_info_is_compatible(node->loaded_info[0], info)) {
-                       pr_warning("could not add '%s' (incompatible "
-                                  "version)\n", info->filename);
+                       pr_warn("could not add '%s' (incompatible "
+                               "version)\n", gcov_info_filename(info));
                        kfree(loaded_info);
                        return;
                }
@@ -691,8 +692,9 @@ static void save_info(struct gcov_node *node, struct gcov_info *info)
        else {
                node->unloaded_info = gcov_info_dup(info);
                if (!node->unloaded_info) {
-                       pr_warning("could not save data for '%s' "
-                                  "(out of memory)\n", info->filename);
+                       pr_warn("could not save data for '%s' "
+                               "(out of memory)\n",
+                               gcov_info_filename(info));
                }
        }
 }
@@ -707,8 +709,8 @@ static void remove_info(struct gcov_node *node, struct gcov_info *info)
 
        i = get_info_index(node, info);
        if (i < 0) {
-               pr_warning("could not remove '%s' (not found)\n",
-                          info->filename);
+               pr_warn("could not remove '%s' (not found)\n",
+                       gcov_info_filename(info));
                return;
        }
        if (gcov_persist)
@@ -735,7 +737,7 @@ void gcov_event(enum gcov_action action, struct gcov_info *info)
        struct gcov_node *node;
 
        mutex_lock(&node_lock);
-       node = get_node_by_name(info->filename);
+       node = get_node_by_name(gcov_info_filename(info));
        switch (action) {
        case GCOV_ADD:
                if (node)
@@ -747,8 +749,8 @@ void gcov_event(enum gcov_action action, struct gcov_info *info)
                if (node)
                        remove_info(node, info);
                else {
-                       pr_warning("could not remove '%s' (not found)\n",
-                                  info->filename);
+                       pr_warn("could not remove '%s' (not found)\n",
+                               gcov_info_filename(info));
                }
                break;
        }
index ae5bb42600335d23ca4336cbead99a79be9bbf60..27bc88a35013de7b3a7c3bac5118fefd1c5bf2d5 100644 (file)
 #include <linux/vmalloc.h>
 #include "gcov.h"
 
+#define GCOV_COUNTERS          5
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @ident: object file-unique function identifier
+ * @checksum: function checksum
+ * @n_ctrs: number of values per counter type belonging to this function
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ */
+struct gcov_fn_info {
+       unsigned int ident;
+       unsigned int checksum;
+       unsigned int n_ctrs[0];
+};
+
+/**
+ * struct gcov_ctr_info - profiling data per counter type
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ * @merge: merge function for counter values of this type (unused)
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+       unsigned int    num;
+       gcov_type       *values;
+       void            (*merge)(gcov_type *, unsigned int);
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: time stamp
+ * @filename: name of the associated gcov data file
+ * @n_functions: number of instrumented functions
+ * @functions: function data
+ * @ctr_mask: mask specifying which counter types are active
+ * @counts: counter data per counter type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+       unsigned int                    version;
+       struct gcov_info                *next;
+       unsigned int                    stamp;
+       const char                      *filename;
+       unsigned int                    n_functions;
+       const struct gcov_fn_info       *functions;
+       unsigned int                    ctr_mask;
+       struct gcov_ctr_info            counts[0];
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+       return info->filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+       return info->version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+       if (!info)
+               return gcov_info_head;
+
+       return info->next;
+}
+
+/**
+ * gcov_info_link - link/add profiling data set to the list
+ * @info: profiling data set
+ */
+void gcov_info_link(struct gcov_info *info)
+{
+       info->next = gcov_info_head;
+       gcov_info_head = info;
+}
+
+/**
+ * gcov_info_unlink - unlink/remove profiling data set from the list
+ * @prev: previous profiling data set
+ * @info: profiling data set
+ */
+void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
+{
+       if (prev)
+               prev->next = info->next;
+       else
+               gcov_info_head = info->next;
+}
+
 /* Symbolic links to be created for each profiling data file. */
 const struct gcov_link gcov_link[] = {
        { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c
new file mode 100644 (file)
index 0000000..2c6e463
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ *  This code provides functions to handle gcc's profiling data format
+ *  introduced with gcc 4.7.
+ *
+ *  This file is based heavily on gcc_3_4.c file.
+ *
+ *  For a better understanding, refer to gcc source:
+ *  gcc/gcov-io.h
+ *  libgcc/libgcov.c
+ *
+ *  Uses gcc-internal data definitions.
+ */
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include "gcov.h"
+
+#define GCOV_COUNTERS                  8
+#define GCOV_TAG_FUNCTION_LENGTH       3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+       unsigned int num;
+       gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function.  This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info.  The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+       const struct gcov_info *key;
+       unsigned int ident;
+       unsigned int lineno_checksum;
+       unsigned int cfg_checksum;
+       struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+       unsigned int version;
+       struct gcov_info *next;
+       unsigned int stamp;
+       const char *filename;
+       void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+       unsigned int n_functions;
+       struct gcov_fn_info **functions;
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+       return info->filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+       return info->version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+       if (!info)
+               return gcov_info_head;
+
+       return info->next;
+}
+
+/**
+ * gcov_info_link - link/add profiling data set to the list
+ * @info: profiling data set
+ */
+void gcov_info_link(struct gcov_info *info)
+{
+       info->next = gcov_info_head;
+       gcov_info_head = info;
+}
+
+/**
+ * gcov_info_unlink - unlink/remove profiling data set from the list
+ * @prev: previous profiling data set
+ * @info: profiling data set
+ */
+void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
+{
+       if (prev)
+               prev->next = info->next;
+       else
+               gcov_info_head = info->next;
+}
+
+/* Symbolic links to be created for each profiling data file. */
+const struct gcov_link gcov_link[] = {
+       { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
+       { 0, NULL},
+};
+
+/*
+ * Determine whether a counter is active. Doesn't change at run-time.
+ */
+static int counter_active(struct gcov_info *info, unsigned int type)
+{
+       return info->merge[type] ? 1 : 0;
+}
+
+/* Determine number of active counters. Based on gcc magic. */
+static unsigned int num_counter_active(struct gcov_info *info)
+{
+       unsigned int i;
+       unsigned int result = 0;
+
+       for (i = 0; i < GCOV_COUNTERS; i++) {
+               if (counter_active(info, i))
+                       result++;
+       }
+       return result;
+}
+
+/**
+ * gcov_info_reset - reset profiling data to zero
+ * @info: profiling data set
+ */
+void gcov_info_reset(struct gcov_info *info)
+{
+       struct gcov_ctr_info *ci_ptr;
+       unsigned int fi_idx;
+       unsigned int ct_idx;
+
+       for (fi_idx = 0; fi_idx < info->n_functions; fi_idx++) {
+               ci_ptr = info->functions[fi_idx]->ctrs;
+
+               for (ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++) {
+                       if (!counter_active(info, ct_idx))
+                               continue;
+
+                       memset(ci_ptr->values, 0,
+                                       sizeof(gcov_type) * ci_ptr->num);
+                       ci_ptr++;
+               }
+       }
+}
+
+/**
+ * gcov_info_is_compatible - check if profiling data can be added
+ * @info1: first profiling data set
+ * @info2: second profiling data set
+ *
+ * Returns non-zero if profiling data can be added, zero otherwise.
+ */
+int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
+{
+       return (info1->stamp == info2->stamp);
+}
+
+/**
+ * gcov_info_add - add up profiling data
+ * @dest: profiling data set to which data is added
+ * @source: profiling data set which is added
+ *
+ * Adds profiling counts of @source to @dest.
+ */
+void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)
+{
+       struct gcov_ctr_info *dci_ptr;
+       struct gcov_ctr_info *sci_ptr;
+       unsigned int fi_idx;
+       unsigned int ct_idx;
+       unsigned int val_idx;
+
+       for (fi_idx = 0; fi_idx < src->n_functions; fi_idx++) {
+               dci_ptr = dst->functions[fi_idx]->ctrs;
+               sci_ptr = src->functions[fi_idx]->ctrs;
+
+               for (ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++) {
+                       if (!counter_active(src, ct_idx))
+                               continue;
+
+                       for (val_idx = 0; val_idx < sci_ptr->num; val_idx++)
+                               dci_ptr->values[val_idx] +=
+                                       sci_ptr->values[val_idx];
+
+                       dci_ptr++;
+                       sci_ptr++;
+               }
+       }
+}
+
+/**
+ * gcov_info_dup - duplicate profiling data set
+ * @info: profiling data set to duplicate
+ *
+ * Return newly allocated duplicate on success, %NULL on error.
+ */
+struct gcov_info *gcov_info_dup(struct gcov_info *info)
+{
+       struct gcov_info *dup;
+       struct gcov_ctr_info *dci_ptr; /* dst counter info */
+       struct gcov_ctr_info *sci_ptr; /* src counter info */
+       unsigned int active;
+       unsigned int fi_idx; /* function info idx */
+       unsigned int ct_idx; /* counter type idx */
+       size_t fi_size; /* function info size */
+       size_t cv_size; /* counter values size */
+
+       dup = kmemdup(info, sizeof(*dup), GFP_KERNEL);
+       if (!dup)
+               return NULL;
+
+       dup->next = NULL;
+       dup->filename = NULL;
+       dup->functions = NULL;
+
+       dup->filename = kstrdup(info->filename, GFP_KERNEL);
+       if (!dup->filename)
+               goto err_free;
+
+       dup->functions = kcalloc(info->n_functions,
+                                sizeof(struct gcov_fn_info *), GFP_KERNEL);
+       if (!dup->functions)
+               goto err_free;
+
+       active = num_counter_active(info);
+       fi_size = sizeof(struct gcov_fn_info);
+       fi_size += sizeof(struct gcov_ctr_info) * active;
+
+       for (fi_idx = 0; fi_idx < info->n_functions; fi_idx++) {
+               dup->functions[fi_idx] = kzalloc(fi_size, GFP_KERNEL);
+               if (!dup->functions[fi_idx])
+                       goto err_free;
+
+               *(dup->functions[fi_idx]) = *(info->functions[fi_idx]);
+
+               sci_ptr = info->functions[fi_idx]->ctrs;
+               dci_ptr = dup->functions[fi_idx]->ctrs;
+
+               for (ct_idx = 0; ct_idx < active; ct_idx++) {
+
+                       cv_size = sizeof(gcov_type) * sci_ptr->num;
+
+                       dci_ptr->values = vmalloc(cv_size);
+
+                       if (!dci_ptr->values)
+                               goto err_free;
+
+                       dci_ptr->num = sci_ptr->num;
+                       memcpy(dci_ptr->values, sci_ptr->values, cv_size);
+
+                       sci_ptr++;
+                       dci_ptr++;
+               }
+       }
+
+       return dup;
+err_free:
+       gcov_info_free(dup);
+       return NULL;
+}
+
+/**
+ * gcov_info_free - release memory for profiling data set duplicate
+ * @info: profiling data set duplicate to free
+ */
+void gcov_info_free(struct gcov_info *info)
+{
+       unsigned int active;
+       unsigned int fi_idx;
+       unsigned int ct_idx;
+       struct gcov_ctr_info *ci_ptr;
+
+       if (!info->functions)
+               goto free_info;
+
+       active = num_counter_active(info);
+
+       for (fi_idx = 0; fi_idx < info->n_functions; fi_idx++) {
+               if (!info->functions[fi_idx])
+                       continue;
+
+               ci_ptr = info->functions[fi_idx]->ctrs;
+
+               for (ct_idx = 0; ct_idx < active; ct_idx++, ci_ptr++)
+                       vfree(ci_ptr->values);
+
+               kfree(info->functions[fi_idx]);
+       }
+
+free_info:
+       kfree(info->functions);
+       kfree(info->filename);
+       kfree(info);
+}
+
+#define ITER_STRIDE    PAGE_SIZE
+
+/**
+ * struct gcov_iterator - specifies current file position in logical records
+ * @info: associated profiling data
+ * @buffer: buffer containing file data
+ * @size: size of buffer
+ * @pos: current position in file
+ */
+struct gcov_iterator {
+       struct gcov_info *info;
+       void *buffer;
+       size_t size;
+       loff_t pos;
+};
+
+/**
+ * store_gcov_u32 - store 32 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
+ * store anything.
+ */
+static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
+{
+       u32 *data;
+
+       if (buffer) {
+               data = buffer + off;
+               *data = v;
+       }
+
+       return sizeof(*data);
+}
+
+/**
+ * store_gcov_u64 - store 64 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. 64 bit numbers are stored as two 32 bit numbers, the low part
+ * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
+ * anything.
+ */
+static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
+{
+       u32 *data;
+
+       if (buffer) {
+               data = buffer + off;
+
+               data[0] = (v & 0xffffffffUL);
+               data[1] = (v >> 32);
+       }
+
+       return sizeof(*data) * 2;
+}
+
+/**
+ * convert_to_gcda - convert profiling data set to gcda file format
+ * @buffer: the buffer to store file data or %NULL if no data should be stored
+ * @info: profiling data set to be converted
+ *
+ * Returns the number of bytes that were/would have been stored into the buffer.
+ */
+static size_t convert_to_gcda(char *buffer, struct gcov_info *info)
+{
+       struct gcov_fn_info *fi_ptr;
+       struct gcov_ctr_info *ci_ptr;
+       unsigned int fi_idx;
+       unsigned int ct_idx;
+       unsigned int cv_idx;
+       size_t pos = 0;
+
+       /* File header. */
+       pos += store_gcov_u32(buffer, pos, GCOV_DATA_MAGIC);
+       pos += store_gcov_u32(buffer, pos, info->version);
+       pos += store_gcov_u32(buffer, pos, info->stamp);
+
+       for (fi_idx = 0; fi_idx < info->n_functions; fi_idx++) {
+               fi_ptr = info->functions[fi_idx];
+
+               /* Function record. */
+               pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
+               pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION_LENGTH);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->lineno_checksum);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
+
+               ci_ptr = fi_ptr->ctrs;
+
+               for (ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++) {
+                       if (!counter_active(info, ct_idx))
+                               continue;
+
+                       /* Counter record. */
+                       pos += store_gcov_u32(buffer, pos,
+                                             GCOV_TAG_FOR_COUNTER(ct_idx));
+                       pos += store_gcov_u32(buffer, pos, ci_ptr->num * 2);
+
+                       for (cv_idx = 0; cv_idx < ci_ptr->num; cv_idx++) {
+                               pos += store_gcov_u64(buffer, pos,
+                                                     ci_ptr->values[cv_idx]);
+                       }
+
+                       ci_ptr++;
+               }
+       }
+
+       return pos;
+}
+
+/**
+ * gcov_iter_new - allocate and initialize profiling data iterator
+ * @info: profiling data set to be iterated
+ *
+ * Return file iterator on success, %NULL otherwise.
+ */
+struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
+{
+       struct gcov_iterator *iter;
+
+       iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
+       if (!iter)
+               goto err_free;
+
+       iter->info = info;
+       /* Dry-run to get the actual buffer size. */
+       iter->size = convert_to_gcda(NULL, info);
+       iter->buffer = vmalloc(iter->size);
+       if (!iter->buffer)
+               goto err_free;
+
+       convert_to_gcda(iter->buffer, info);
+
+       return iter;
+
+err_free:
+       kfree(iter);
+       return NULL;
+}
+
+
+/**
+ * gcov_iter_get_info - return profiling data set for given file iterator
+ * @iter: file iterator
+ */
+void gcov_iter_free(struct gcov_iterator *iter)
+{
+       vfree(iter->buffer);
+       kfree(iter);
+}
+
+/**
+ * gcov_iter_get_info - return profiling data set for given file iterator
+ * @iter: file iterator
+ */
+struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
+{
+       return iter->info;
+}
+
+/**
+ * gcov_iter_start - reset file iterator to starting position
+ * @iter: file iterator
+ */
+void gcov_iter_start(struct gcov_iterator *iter)
+{
+       iter->pos = 0;
+}
+
+/**
+ * gcov_iter_next - advance file iterator to next logical record
+ * @iter: file iterator
+ *
+ * Return zero if new position is valid, non-zero if iterator has reached end.
+ */
+int gcov_iter_next(struct gcov_iterator *iter)
+{
+       if (iter->pos < iter->size)
+               iter->pos += ITER_STRIDE;
+
+       if (iter->pos >= iter->size)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * gcov_iter_write - write data for current pos to seq_file
+ * @iter: file iterator
+ * @seq: seq_file handle
+ *
+ * Return zero on success, non-zero otherwise.
+ */
+int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
+{
+       size_t len;
+
+       if (iter->pos >= iter->size)
+               return -EINVAL;
+
+       len = ITER_STRIDE;
+       if (iter->pos + len > iter->size)
+               len = iter->size - iter->pos;
+
+       seq_write(seq, iter->buffer + iter->pos, len);
+
+       return 0;
+}
index 060073ebf7a638111d6838d8fe187d077d5f48f6..92c8e22a29ede59be2c942fda5a07ff1c63849f5 100644 (file)
@@ -21,7 +21,6 @@
  * gcc and need to be kept as close to the original definition as possible to
  * remain compatible.
  */
-#define GCOV_COUNTERS          5
 #define GCOV_DATA_MAGIC                ((unsigned int) 0x67636461)
 #define GCOV_TAG_FUNCTION      ((unsigned int) 0x01000000)
 #define GCOV_TAG_COUNTER_BASE  ((unsigned int) 0x01a10000)
@@ -34,60 +33,18 @@ typedef long gcov_type;
 typedef long long gcov_type;
 #endif
 
-/**
- * struct gcov_fn_info - profiling meta data per function
- * @ident: object file-unique function identifier
- * @checksum: function checksum
- * @n_ctrs: number of values per counter type belonging to this function
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time.
- */
-struct gcov_fn_info {
-       unsigned int ident;
-       unsigned int checksum;
-       unsigned int n_ctrs[0];
-};
-
-/**
- * struct gcov_ctr_info - profiling data per counter type
- * @num: number of counter values for this type
- * @values: array of counter values for this type
- * @merge: merge function for counter values of this type (unused)
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the values array.
- */
-struct gcov_ctr_info {
-       unsigned int    num;
-       gcov_type       *values;
-       void            (*merge)(gcov_type *, unsigned int);
-};
+/* Opaque gcov_info. The gcov structures can change as for example in gcc 4.7 so
+ * we cannot use full definition here and they need to be placed in gcc specific
+ * implementation of gcov. This also means no direct access to the members in
+ * generic code and usage of the interface below.*/
+struct gcov_info;
 
-/**
- * struct gcov_info - profiling data per object file
- * @version: gcov version magic indicating the gcc version used for compilation
- * @next: list head for a singly-linked list
- * @stamp: time stamp
- * @filename: name of the associated gcov data file
- * @n_functions: number of instrumented functions
- * @functions: function data
- * @ctr_mask: mask specifying which counter types are active
- * @counts: counter data per counter type
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the next pointer.
- */
-struct gcov_info {
-       unsigned int                    version;
-       struct gcov_info                *next;
-       unsigned int                    stamp;
-       const char                      *filename;
-       unsigned int                    n_functions;
-       const struct gcov_fn_info       *functions;
-       unsigned int                    ctr_mask;
-       struct gcov_ctr_info            counts[0];
-};
+/* Interface to access gcov_info data  */
+const char *gcov_info_filename(struct gcov_info *info);
+unsigned int gcov_info_version(struct gcov_info *info);
+struct gcov_info *gcov_info_next(struct gcov_info *info);
+void gcov_info_link(struct gcov_info *info);
+void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);
 
 /* Base interface. */
 enum gcov_action {
index a0d367a49122ea39ddb060c7a2a2ecd60855e6f9..ceeadfcabb7611defdbb10f66f3a6b23e60fb0ed 100644 (file)
@@ -2066,7 +2066,7 @@ static int __init init_kprobes(void)
 {
        int i, err = 0;
        unsigned long offset = 0, size = 0;
-       char *modname, namebuf[128];
+       char *modname, namebuf[KSYM_NAME_LEN];
        const char *symbol_name;
        void *addr;
        struct kprobe_blackpoint *kb;
@@ -2192,7 +2192,7 @@ static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
        const char *sym = NULL;
        unsigned int i = *(loff_t *) v;
        unsigned long offset = 0;
-       char *modname, namebuf[128];
+       char *modname, namebuf[KSYM_NAME_LEN];
 
        head = &kprobe_table[i];
        preempt_disable();
index 760e86df8c204dc60c23e18b01bdec314780ba1e..b5ae3ee860a9a520d1ea78d15ecdb94b75a02cca 100644 (file)
@@ -33,7 +33,7 @@ struct kthread_create_info
 
        /* Result passed back to kthread_create() from kthreadd. */
        struct task_struct *result;
-       struct completion done;
+       struct completion *done;
 
        struct list_head list;
 };
@@ -178,6 +178,7 @@ static int kthread(void *_create)
        struct kthread_create_info *create = _create;
        int (*threadfn)(void *data) = create->threadfn;
        void *data = create->data;
+       struct completion *done;
        struct kthread self;
        int ret;
 
@@ -187,10 +188,16 @@ static int kthread(void *_create)
        init_completion(&self.parked);
        current->vfork_done = &self.exited;
 
+       /* If user was SIGKILLed, I release the structure. */
+       done = xchg(&create->done, NULL);
+       if (!done) {
+               kfree(create);
+               do_exit(-EINTR);
+       }
        /* OK, tell user we're spawned, wait for stop or wakeup */
        __set_current_state(TASK_UNINTERRUPTIBLE);
        create->result = current;
-       complete(&create->done);
+       complete(done);
        schedule();
 
        ret = -EINTR;
@@ -223,8 +230,15 @@ static void create_kthread(struct kthread_create_info *create)
        /* We want our own signal handler (we take no signals by default). */
        pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
        if (pid < 0) {
+               /* If user was SIGKILLed, I release the structure. */
+               struct completion *done = xchg(&create->done, NULL);
+
+               if (!done) {
+                       kfree(create);
+                       return;
+               }
                create->result = ERR_PTR(pid);
-               complete(&create->done);
+               complete(done);
        }
 }
 
@@ -255,36 +269,59 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
                                           const char namefmt[],
                                           ...)
 {
-       struct kthread_create_info create;
-
-       create.threadfn = threadfn;
-       create.data = data;
-       create.node = node;
-       init_completion(&create.done);
+       DECLARE_COMPLETION_ONSTACK(done);
+       struct task_struct *task;
+       struct kthread_create_info *create = kmalloc(sizeof(*create),
+                                                    GFP_KERNEL);
+
+       if (!create)
+               return ERR_PTR(-ENOMEM);
+       create->threadfn = threadfn;
+       create->data = data;
+       create->node = node;
+       create->done = &done;
 
        spin_lock(&kthread_create_lock);
-       list_add_tail(&create.list, &kthread_create_list);
+       list_add_tail(&create->list, &kthread_create_list);
        spin_unlock(&kthread_create_lock);
 
        wake_up_process(kthreadd_task);
-       wait_for_completion(&create.done);
-
-       if (!IS_ERR(create.result)) {
+       /*
+        * Wait for completion in killable state, for I might be chosen by
+        * the OOM killer while kthreadd is trying to allocate memory for
+        * new kernel thread.
+        */
+       if (unlikely(wait_for_completion_killable(&done))) {
+               /*
+                * If I was SIGKILLed before kthreadd (or new kernel thread)
+                * calls complete(), leave the cleanup of this structure to
+                * that thread.
+                */
+               if (xchg(&create->done, NULL))
+                       return ERR_PTR(-ENOMEM);
+               /*
+                * kthreadd (or new kernel thread) will call complete()
+                * shortly.
+                */
+               wait_for_completion(&done);
+       }
+       task = create->result;
+       if (!IS_ERR(task)) {
                static const struct sched_param param = { .sched_priority = 0 };
                va_list args;
 
                va_start(args, namefmt);
-               vsnprintf(create.result->comm, sizeof(create.result->comm),
-                         namefmt, args);
+               vsnprintf(task->comm, sizeof(task->comm), namefmt, args);
                va_end(args);
                /*
                 * root may have changed our (kthreadd's) priority or CPU mask.
                 * The kernel thread should not inherit these properties.
                 */
-               sched_setscheduler_nocheck(create.result, SCHED_NORMAL, &param);
-               set_cpus_allowed_ptr(create.result, cpu_all_mask);
+               sched_setscheduler_nocheck(task, SCHED_NORMAL, &param);
+               set_cpus_allowed_ptr(task, cpu_all_mask);
        }
-       return create.result;
+       kfree(create);
+       return task;
 }
 EXPORT_SYMBOL(kthread_create_on_node);
 
index dc582749fa1386db25af23929db4fc20b6c7acce..af5ebd21d77bae35906044e90271b7578093afa2 100644 (file)
@@ -378,23 +378,21 @@ static bool check_symbol(const struct symsearch *syms,
                if (syms->licence == GPL_ONLY)
                        return false;
                if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {
-                       printk(KERN_WARNING "Symbol %s is being used "
-                              "by a non-GPL module, which will not "
-                              "be allowed in the future\n", fsa->name);
+                       pr_warn("Symbol %s is being used by a non-GPL module, "
+                               "which will not be allowed in the future\n",
+                               fsa->name);
                }
        }
 
 #ifdef CONFIG_UNUSED_SYMBOLS
        if (syms->unused && fsa->warn) {
-               printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
-                      "however this module is using it.\n", fsa->name);
-               printk(KERN_WARNING
-                      "This symbol will go away in the future.\n");
-               printk(KERN_WARNING
-                      "Please evalute if this is the right api to use and if "
-                      "it really is, submit a report the linux kernel "
-                      "mailinglist together with submitting your code for "
-                      "inclusion.\n");
+               pr_warn("Symbol %s is marked as UNUSED, however this module is "
+                       "using it.\n", fsa->name);
+               pr_warn("This symbol will go away in the future.\n");
+               pr_warn("Please evalute if this is the right api to use and if "
+                       "it really is, submit a report the linux kernel "
+                       "mailinglist together with submitting your code for "
+                       "inclusion.\n");
        }
 #endif
 
@@ -492,16 +490,15 @@ static int percpu_modalloc(struct module *mod, struct load_info *info)
                return 0;
 
        if (align > PAGE_SIZE) {
-               printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
-                      mod->name, align, PAGE_SIZE);
+               pr_warn("%s: per-cpu alignment %li > %li\n",
+                       mod->name, align, PAGE_SIZE);
                align = PAGE_SIZE;
        }
 
        mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align);
        if (!mod->percpu) {
-               printk(KERN_WARNING
-                      "%s: Could not allocate %lu bytes percpu data\n",
-                      mod->name, (unsigned long)pcpusec->sh_size);
+               pr_warn("%s: Could not allocate %lu bytes percpu data\n",
+                       mod->name, (unsigned long)pcpusec->sh_size);
                return -ENOMEM;
        }
        mod->percpu_size = pcpusec->sh_size;
@@ -679,7 +676,7 @@ static int add_module_usage(struct module *a, struct module *b)
        pr_debug("Allocating new usage for %s.\n", a->name);
        use = kmalloc(sizeof(*use), GFP_ATOMIC);
        if (!use) {
-               printk(KERN_WARNING "%s: out of memory loading\n", a->name);
+               pr_warn("%s: out of memory loading\n", a->name);
                return -ENOMEM;
        }
 
@@ -1145,8 +1142,7 @@ static int try_to_force_load(struct module *mod, const char *reason)
 {
 #ifdef CONFIG_MODULE_FORCE_LOAD
        if (!test_taint(TAINT_FORCED_MODULE))
-               printk(KERN_WARNING "%s: %s: kernel tainted.\n",
-                      mod->name, reason);
+               pr_warn("%s: %s: kernel tainted.\n", mod->name, reason);
        add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_NOW_UNRELIABLE);
        return 0;
 #else
@@ -1199,8 +1195,7 @@ static int check_version(Elf_Shdr *sechdrs,
                goto bad_version;
        }
 
-       printk(KERN_WARNING "%s: no symbol version for %s\n",
-              mod->name, symname);
+       pr_warn("%s: no symbol version for %s\n", mod->name, symname);
        return 0;
 
 bad_version:
@@ -1309,8 +1304,8 @@ resolve_symbol_wait(struct module *mod,
                        !IS_ERR(ksym = resolve_symbol(mod, info, name, owner))
                        || PTR_ERR(ksym) != -EBUSY,
                                             30 * HZ) <= 0) {
-               printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
-                      mod->name, owner);
+               pr_warn("%s: gave up waiting for init of module %s.\n",
+                       mod->name, owner);
        }
        return ksym;
 }
@@ -1626,15 +1621,14 @@ static int mod_sysfs_init(struct module *mod)
        struct kobject *kobj;
 
        if (!module_sysfs_initialized) {
-               printk(KERN_ERR "%s: module sysfs not initialized\n",
-                      mod->name);
+               pr_err("%s: module sysfs not initialized\n", mod->name);
                err = -EINVAL;
                goto out;
        }
 
        kobj = kset_find_obj(module_kset, mod->name);
        if (kobj) {
-               printk(KERN_ERR "%s: module is already loaded\n", mod->name);
+               pr_err("%s: module is already loaded\n", mod->name);
                kobject_put(kobj);
                err = -EINVAL;
                goto out;
@@ -1961,8 +1955,7 @@ static int verify_export_symbols(struct module *mod)
        for (i = 0; i < ARRAY_SIZE(arr); i++) {
                for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
                        if (find_symbol(s->name, &owner, NULL, true, false)) {
-                               printk(KERN_ERR
-                                      "%s: exports duplicate symbol %s"
+                               pr_err("%s: exports duplicate symbol %s"
                                       " (owned by %s)\n",
                                       mod->name, s->name, module_name(owner));
                                return -ENOEXEC;
@@ -2013,8 +2006,8 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
                        if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
                                break;
 
-                       printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
-                              mod->name, name, PTR_ERR(ksym));
+                       pr_warn("%s: Unknown symbol %s (err %li)\n",
+                               mod->name, name, PTR_ERR(ksym));
                        ret = PTR_ERR(ksym) ?: -ENOENT;
                        break;
 
@@ -2168,8 +2161,8 @@ static void set_license(struct module *mod, const char *license)
 
        if (!license_is_gpl_compatible(license)) {
                if (!test_taint(TAINT_PROPRIETARY_MODULE))
-                       printk(KERN_WARNING "%s: module license '%s' taints "
-                               "kernel.\n", mod->name, license);
+                       pr_warn("%s: module license '%s' taints kernel.\n",
+                               mod->name, license);
                add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
                                 LOCKDEP_NOW_UNRELIABLE);
        }
@@ -2405,8 +2398,8 @@ static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
                return;
 #ifdef CONFIG_DYNAMIC_DEBUG
        if (ddebug_add_module(debug, num, debug->modname))
-               printk(KERN_ERR "dynamic debug error adding module: %s\n",
-                                       debug->modname);
+               pr_err("dynamic debug error adding module: %s\n",
+                       debug->modname);
 #endif
 }
 
@@ -2619,8 +2612,7 @@ static int rewrite_section_headers(struct load_info *info, int flags)
                Elf_Shdr *shdr = &info->sechdrs[i];
                if (shdr->sh_type != SHT_NOBITS
                    && info->len < shdr->sh_offset + shdr->sh_size) {
-                       printk(KERN_ERR "Module len %lu truncated\n",
-                              info->len);
+                       pr_err("Module len %lu truncated\n", info->len);
                        return -ENOEXEC;
                }
 
@@ -2682,15 +2674,14 @@ static struct module *setup_load_info(struct load_info *info, int flags)
 
        info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
        if (!info->index.mod) {
-               printk(KERN_WARNING "No module found in object\n");
+               pr_warn("No module found in object\n");
                return ERR_PTR(-ENOEXEC);
        }
        /* This is temporary: point mod into copy of data. */
        mod = (void *)info->sechdrs[info->index.mod].sh_addr;
 
        if (info->index.sym == 0) {
-               printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
-                      mod->name);
+               pr_warn("%s: module has no symbols (stripped?)\n", mod->name);
                return ERR_PTR(-ENOEXEC);
        }
 
@@ -2717,7 +2708,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
                if (err)
                        return err;
        } else if (!same_magic(modmagic, vermagic, info->index.vers)) {
-               printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
+               pr_err("%s: version magic '%s' should be '%s'\n",
                       mod->name, modmagic, vermagic);
                return -ENOEXEC;
        }
@@ -2727,9 +2718,8 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
 
        if (get_modinfo(info, "staging")) {
                add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
-               printk(KERN_WARNING "%s: module is from the staging directory,"
-                      " the quality is unknown, you have been warned.\n",
-                      mod->name);
+               pr_warn("%s: module is from the staging directory, the quality "
+                       "is unknown, you have been warned.\n", mod->name);
        }
 
        /* Set up license info based on the info section */
@@ -2801,8 +2791,7 @@ static void find_module_sections(struct module *mod, struct load_info *info)
                                    sizeof(*mod->extable), &mod->num_exentries);
 
        if (section_addr(info, "__obsparm"))
-               printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
-                      mod->name);
+               pr_warn("%s: Ignoring obsolete parameters\n", mod->name);
 
        info->debug = section_objs(info, "__verbose",
                                   sizeof(*info->debug), &info->num_debug);
@@ -3078,11 +3067,10 @@ static int do_init_module(struct module *mod)
                return ret;
        }
        if (ret > 0) {
-               printk(KERN_WARNING
-"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
-"%s: loading module anyway...\n",
-                      __func__, mod->name, ret,
-                      __func__);
+               pr_warn("%s: '%s'->init suspiciously returned %d, it should "
+                       "follow 0/-E convention\n"
+                       "%s: loading module anyway...\n",
+                       __func__, mod->name, ret, __func__);
                dump_stack();
        }
 
@@ -3205,10 +3193,8 @@ static int unknown_module_param_cb(char *param, char *val, const char *modname)
 {
        /* Check for magic 'dyndbg' arg */ 
        int ret = ddebug_dyndbg_module_param_cb(param, val, modname);
-       if (ret != 0) {
-               printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n",
-                      modname, param);
-       }
+       if (ret != 0)
+               pr_warn("%s: unknown parameter '%s' ignored\n", modname, param);
        return 0;
 }
 
@@ -3243,10 +3229,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
 #ifdef CONFIG_MODULE_SIG
        mod->sig_ok = info->sig_ok;
        if (!mod->sig_ok) {
-               printk_once(KERN_NOTICE
-                           "%s: module verification failed: signature and/or"
-                           " required key missing - tainting kernel\n",
-                           mod->name);
+               pr_notice_once("%s: module verification failed: signature "
+                              "and/or  required key missing - tainting "
+                              "kernel\n", mod->name);
                add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_STILL_OK);
        }
 #endif
index b6c482ccc5db77f4af0afbb0948ff0373bb094d5..c00b4ceb39e8b151aab790e6b498247ea53a4aa6 100644 (file)
@@ -233,7 +233,7 @@ static const struct tnt tnts[] = {
  */
 const char *print_tainted(void)
 {
-       static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ") + 1];
+       static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ")];
 
        if (tainted_mask) {
                char *s;
index b4e8500afdb305ad5368ae9a224c6dd2ea7789c7..be7c86bae5762e4e5283dcbd305951301310c58d 100644 (file)
@@ -705,9 +705,9 @@ const struct file_operations kmsg_fops = {
 
 #ifdef CONFIG_KEXEC
 /*
- * This appends the listed symbols to /proc/vmcoreinfo
+ * This appends the listed symbols to /proc/vmcore
  *
- * /proc/vmcoreinfo is used by various utiilties, like crash and makedumpfile to
+ * /proc/vmcore is used by various utilities, like crash and makedumpfile to
  * obtain access to symbols that are otherwise very difficult to locate.  These
  * symbols are specifically used so that utilities can access and extract the
  * dmesg log from a vmcore file after a crash.
@@ -791,7 +791,7 @@ static bool __read_mostly ignore_loglevel;
 static int __init ignore_loglevel_setup(char *str)
 {
        ignore_loglevel = 1;
-       printk(KERN_INFO "debug: ignoring loglevel setting.\n");
+       pr_info("debug: ignoring loglevel setting.\n");
 
        return 0;
 }
@@ -820,9 +820,9 @@ static int __init boot_delay_setup(char *str)
        pr_debug("boot_delay: %u, preset_lpj: %ld, lpj: %lu, "
                "HZ: %d, loops_per_msec: %llu\n",
                boot_delay, preset_lpj, lpj, HZ, loops_per_msec);
-       return 1;
+       return 0;
 }
-__setup("boot_delay=", boot_delay_setup);
+early_param("boot_delay", boot_delay_setup);
 
 static void boot_delay_msec(int level)
 {
@@ -2193,7 +2193,7 @@ static int __read_mostly keep_bootcon;
 static int __init keep_bootcon_setup(char *str)
 {
        keep_bootcon = 1;
-       printk(KERN_INFO "debug: skip boot console de-registration.\n");
+       pr_info("debug: skip boot console de-registration.\n");
 
        return 0;
 }
@@ -2241,7 +2241,7 @@ void register_console(struct console *newcon)
                /* find the last or real console */
                for_each_console(bcon) {
                        if (!(bcon->flags & CON_BOOT)) {
-                               printk(KERN_INFO "Too late to register bootconsole %s%d\n",
+                               pr_info("Too late to register bootconsole %s%d\n",
                                        newcon->name, newcon->index);
                                return;
                        }
@@ -2358,21 +2358,18 @@ void register_console(struct console *newcon)
         * users know there might be something in the kernel's log buffer that
         * went to the bootconsole (that they do not see on the real console)
         */
+       pr_info("%sconsole [%s%d] enabled\n",
+               (newcon->flags & CON_BOOT) ? "boot" : "" ,
+               newcon->name, newcon->index);
        if (bcon &&
            ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
            !keep_bootcon) {
-               /* we need to iterate through twice, to make sure we print
-                * everything out, before we unregister the console(s)
+               /* We need to iterate through all boot consoles, to make
+                * sure we print everything out, before we unregister them.
                 */
-               printk(KERN_INFO "console [%s%d] enabled, bootconsole disabled\n",
-                       newcon->name, newcon->index);
                for_each_console(bcon)
                        if (bcon->flags & CON_BOOT)
                                unregister_console(bcon);
-       } else {
-               printk(KERN_INFO "%sconsole [%s%d] enabled\n",
-                       (newcon->flags & CON_BOOT) ? "boot" : "" ,
-                       newcon->name, newcon->index);
        }
 }
 EXPORT_SYMBOL(register_console);
@@ -2382,6 +2379,10 @@ int unregister_console(struct console *console)
         struct console *a, *b;
        int res;
 
+       pr_info("%sconsole [%s%d] disabled\n",
+               (console->flags & CON_BOOT) ? "boot" : "" ,
+               console->name, console->index);
+
        res = _braille_unregister_console(console);
        if (res)
                return res;
@@ -2421,8 +2422,6 @@ static int __init printk_late_init(void)
 
        for_each_console(con) {
                if (!keep_bootcon && con->flags & CON_BOOT) {
-                       printk(KERN_INFO "turn off boot console %s%d\n",
-                               con->name, con->index);
                        unregister_console(con);
                }
        }
@@ -2449,7 +2448,7 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work)
 
        if (pending & PRINTK_PENDING_SCHED) {
                char *buf = __get_cpu_var(printk_sched_buf);
-               printk(KERN_WARNING "[sched_delayed] %s", buf);
+               pr_warn("[sched_delayed] %s", buf);
        }
 
        if (pending & PRINTK_PENDING_WAKEUP)
index dd562e9aa2c8419b02067c4883c674989a694cd2..1f4bcb3cc21cee5bcfd1b4e13a77eeff2af23a2b 100644 (file)
@@ -257,7 +257,8 @@ ok:
        if (task->mm)
                dumpable = get_dumpable(task->mm);
        rcu_read_lock();
-       if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
+       if (dumpable != SUID_DUMP_USER &&
+           !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
                rcu_read_unlock();
                return -EPERM;
        }
index c18ecca575b42e0dcc9e12e2fc5c279983d9eb57..c72311324ea76ef2c9ae9514d2a30e4aa7c4be66 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/perf_event.h>
 #include <linux/resource.h>
 #include <linux/kernel.h>
-#include <linux/kexec.h>
 #include <linux/workqueue.h>
 #include <linux/capability.h>
 #include <linux/device.h>
index 36547dddcdb83eab551d0ee60fa34218067d1028..d37d9dd8f4635069bf65bd2a10b00e1595ae7b64 100644 (file)
@@ -2222,8 +2222,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                        *i = val;
                } else {
                        val = convdiv * (*i) / convmul;
-                       if (!first)
+                       if (!first) {
                                err = proc_put_char(&buffer, &left, '\t');
+                               if (err)
+                                       break;
+                       }
                        err = proc_put_long(&buffer, &left, val, false);
                        if (err)
                                break;
index b609213ca9a2f310f169a4d08c08cf1c36f56791..653cbbd9e7ad4dcb1ee0647c6d11cc453b1e81a9 100644 (file)
@@ -1024,7 +1024,7 @@ static ssize_t bin_intvec(struct file *file,
                        if (get_user(value, vec + i))
                                goto out_kfree;
 
-                       str += snprintf(str, end - str, "%lu\t", value);
+                       str += scnprintf(str, end - str, "%lu\t", value);
                }
 
                result = kernel_write(file, buffer, str - buffer, 0);
@@ -1095,7 +1095,7 @@ static ssize_t bin_ulongvec(struct file *file,
                        if (get_user(value, vec + i))
                                goto out_kfree;
 
-                       str += snprintf(str, end - str, "%lu\t", value);
+                       str += scnprintf(str, end - str, "%lu\t", value);
                }
 
                result = kernel_write(file, buffer, str - buffer, 0);
@@ -1205,7 +1205,7 @@ static ssize_t bin_dn_node_address(struct file *file,
                if (get_user(dnaddr, (__le16 __user *)newval))
                        goto out;
 
-               len = snprintf(buf, sizeof(buf), "%hu.%hu",
+               len = scnprintf(buf, sizeof(buf), "%hu.%hu",
                                le16_to_cpu(dnaddr) >> 10,
                                le16_to_cpu(dnaddr) & 0x3ff);
 
index 145bb4d3bd4d9569fb38b33d9afe3496325a6a57..9f4618eb51c8528fe808d91f6dfdc6237af3ab65 100644 (file)
@@ -290,6 +290,7 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
        struct listener_list *listeners;
        struct listener *s, *tmp, *s2;
        unsigned int cpu;
+       int ret = 0;
 
        if (!cpumask_subset(mask, cpu_possible_mask))
                return -EINVAL;
@@ -304,9 +305,10 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
                for_each_cpu(cpu, mask) {
                        s = kmalloc_node(sizeof(struct listener),
                                        GFP_KERNEL, cpu_to_node(cpu));
-                       if (!s)
+                       if (!s) {
+                               ret = -ENOMEM;
                                goto cleanup;
-
+                       }
                        s->pid = pid;
                        s->valid = 1;
 
@@ -339,7 +341,7 @@ cleanup:
                }
                up_write(&listeners->sem);
        }
-       return 0;
+       return ret;
 }
 
 static int parse(struct nlattr *na, struct cpumask *mask)
@@ -404,11 +406,15 @@ static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
        if (!na)
                goto err;
 
-       if (nla_put(skb, type, sizeof(pid), &pid) < 0)
+       if (nla_put(skb, type, sizeof(pid), &pid) < 0) {
+               nla_nest_cancel(skb, na);
                goto err;
+       }
        ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats));
-       if (!ret)
+       if (!ret) {
+               nla_nest_cancel(skb, na);
                goto err;
+       }
        nla_nest_end(skb, na);
 
        return nla_data(ret);
index ebef88f61b7d81b1497cc2619e8d84a525b3471d..db25707aa41bc021b8174391091178b85258d466 100644 (file)
@@ -1481,6 +1481,15 @@ config INTERVAL_TREE_TEST
        help
          A benchmark measuring the performance of the interval tree library
 
+config PERCPU_TEST
+       tristate "Per cpu operations test"
+       depends on m && DEBUG_KERNEL
+       help
+         Enable this option to build test module which validates per-cpu
+         operations.
+
+         If unsure, say N.
+
 config ATOMIC64_SELFTEST
        bool "Perform an atomic64_t self-test at boot"
        help
index f3bb2cb98adfd2a631144ecbde775f6f224bea4e..bb016e116ba43286ed28ca7bf2667c081d752e81 100644 (file)
@@ -157,6 +157,8 @@ obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o
 
 interval_tree_test-objs := interval_tree_test_main.o interval_tree.o
 
+obj-$(CONFIG_PERCPU_TEST) += percpu_test.o
+
 obj-$(CONFIG_ASN1) += asn1_decoder.o
 
 obj-$(CONFIG_FONT_SUPPORT) += fonts/
index bf2c8b1043d8bb5a8b44d19a139842ffb5514067..e0731c3db7069753ebd312824741783c0e41bf2c 100644 (file)
@@ -196,7 +196,7 @@ static void free_object(struct debug_obj *obj)
         * initialized:
         */
        if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache)
-               sched = keventd_up() && !work_pending(&debug_obj_work);
+               sched = keventd_up();
        hlist_add_head(&obj->node, &obj_pool);
        obj_pool_free++;
        obj_pool_used--;
index 2f31e6a45f0af3f4e4bccd38aeb1d8324c72eeff..8793aeda30ca36a72106d3649b62456f00cc7c56 100644 (file)
@@ -209,7 +209,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen,
                kref = keyring_search(make_key_ref(keyring, 1UL),
                                                &key_type_user, name);
                if (IS_ERR(kref))
-                       key = ERR_PTR(PTR_ERR(kref));
+                       key = ERR_CAST(kref);
                else
                        key = key_ref_to_ptr(kref);
        } else {
index 26cf20be72b74013dd874abc551c3f9a412bc1b6..dda31168844f42c9c6fe2f9c9d25526e30884529 100644 (file)
@@ -312,6 +312,34 @@ retry:
 }
 EXPORT_SYMBOL(gen_pool_alloc);
 
+/**
+ * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
+ * @pool: pool to allocate from
+ * @size: number of bytes to allocate from the pool
+ * @dma: dma-view physical address
+ *
+ * Allocate the requested number of bytes from the specified pool.
+ * Uses the pool allocation function (with first-fit algorithm by default).
+ * Can not be used in NMI handler on architectures without
+ * NMI-safe cmpxchg implementation.
+ */
+void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
+{
+       unsigned long vaddr;
+
+       if (!pool)
+               return NULL;
+
+       vaddr = gen_pool_alloc(pool, size);
+       if (!vaddr)
+               return NULL;
+
+       *dma = gen_pool_virt_to_phys(pool, vaddr);
+
+       return (void *)vaddr;
+}
+EXPORT_SYMBOL(gen_pool_dma_alloc);
+
 /**
  * gen_pool_free - free allocated special memory back to the pool
  * @pool: pool to free to
diff --git a/lib/percpu_test.c b/lib/percpu_test.c
new file mode 100644 (file)
index 0000000..0b5d14d
--- /dev/null
@@ -0,0 +1,138 @@
+#include <linux/module.h>
+
+/* validate @native and @pcp counter values match @expected */
+#define CHECK(native, pcp, expected)                                    \
+       do {                                                            \
+               WARN((native) != (expected),                            \
+                    "raw %ld (0x%lx) != expected %lld (0x%llx)",       \
+                    (native), (native),                                \
+                    (long long)(expected), (long long)(expected));     \
+               WARN(__this_cpu_read(pcp) != (expected),                \
+                    "pcp %ld (0x%lx) != expected %lld (0x%llx)",       \
+                    __this_cpu_read(pcp), __this_cpu_read(pcp),        \
+                    (long long)(expected), (long long)(expected));     \
+       } while (0)
+
+static DEFINE_PER_CPU(long, long_counter);
+static DEFINE_PER_CPU(unsigned long, ulong_counter);
+
+static int __init percpu_test_init(void)
+{
+       /*
+        * volatile prevents compiler from optimizing it uses, otherwise the
+        * +ul_one/-ul_one below would replace with inc/dec instructions.
+        */
+       volatile unsigned int ui_one = 1;
+       long l = 0;
+       unsigned long ul = 0;
+
+       pr_info("percpu test start\n");
+
+       preempt_disable();
+
+       l += -1;
+       __this_cpu_add(long_counter, -1);
+       CHECK(l, long_counter, -1);
+
+       l += 1;
+       __this_cpu_add(long_counter, 1);
+       CHECK(l, long_counter, 0);
+
+       ul = 0;
+       __this_cpu_write(ulong_counter, 0);
+
+       ul += 1UL;
+       __this_cpu_add(ulong_counter, 1UL);
+       CHECK(ul, ulong_counter, 1);
+
+       ul += -1UL;
+       __this_cpu_add(ulong_counter, -1UL);
+       CHECK(ul, ulong_counter, 0);
+
+       ul += -(unsigned long)1;
+       __this_cpu_add(ulong_counter, -(unsigned long)1);
+       CHECK(ul, ulong_counter, -1);
+
+       ul = 0;
+       __this_cpu_write(ulong_counter, 0);
+
+       ul -= 1;
+       __this_cpu_dec(ulong_counter);
+       CHECK(ul, ulong_counter, -1);
+       CHECK(ul, ulong_counter, ULONG_MAX);
+
+       l += -ui_one;
+       __this_cpu_add(long_counter, -ui_one);
+       CHECK(l, long_counter, 0xffffffff);
+
+       l += ui_one;
+       __this_cpu_add(long_counter, ui_one);
+       CHECK(l, long_counter, (long)0x100000000LL);
+
+
+       l = 0;
+       __this_cpu_write(long_counter, 0);
+
+       l -= ui_one;
+       __this_cpu_sub(long_counter, ui_one);
+       CHECK(l, long_counter, -1);
+
+       l = 0;
+       __this_cpu_write(long_counter, 0);
+
+       l += ui_one;
+       __this_cpu_add(long_counter, ui_one);
+       CHECK(l, long_counter, 1);
+
+       l += -ui_one;
+       __this_cpu_add(long_counter, -ui_one);
+       CHECK(l, long_counter, (long)0x100000000LL);
+
+       l = 0;
+       __this_cpu_write(long_counter, 0);
+
+       l -= ui_one;
+       this_cpu_sub(long_counter, ui_one);
+       CHECK(l, long_counter, -1);
+       CHECK(l, long_counter, ULONG_MAX);
+
+       ul = 0;
+       __this_cpu_write(ulong_counter, 0);
+
+       ul += ui_one;
+       __this_cpu_add(ulong_counter, ui_one);
+       CHECK(ul, ulong_counter, 1);
+
+       ul = 0;
+       __this_cpu_write(ulong_counter, 0);
+
+       ul -= ui_one;
+       __this_cpu_sub(ulong_counter, ui_one);
+       CHECK(ul, ulong_counter, -1);
+       CHECK(ul, ulong_counter, ULONG_MAX);
+
+       ul = 3;
+       __this_cpu_write(ulong_counter, 3);
+
+       ul = this_cpu_sub_return(ulong_counter, ui_one);
+       CHECK(ul, ulong_counter, 2);
+
+       ul = __this_cpu_sub_return(ulong_counter, ui_one);
+       CHECK(ul, ulong_counter, 1);
+
+       preempt_enable();
+
+       pr_info("percpu test done\n");
+       return -EAGAIN;  /* Fail will directly unload the module */
+}
+
+static void __exit percpu_test_exit(void)
+{
+}
+
+module_init(percpu_test_init)
+module_exit(percpu_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Thelen");
+MODULE_DESCRIPTION("percpu operations test");
index b7c72311ad0c88673546aa910c32cdc5214f96b2..5847a4921b8ee25f5fd88624cd74970da371f2ca 100644 (file)
@@ -12,8 +12,7 @@
 void show_mem(unsigned int filter)
 {
        pg_data_t *pgdat;
-       unsigned long total = 0, reserved = 0, shared = 0,
-               nonshared = 0, highmem = 0;
+       unsigned long total = 0, reserved = 0, highmem = 0;
 
        printk("Mem-Info:\n");
        show_free_areas(filter);
@@ -22,43 +21,27 @@ void show_mem(unsigned int filter)
                return;
 
        for_each_online_pgdat(pgdat) {
-               unsigned long i, flags;
+               unsigned long flags;
+               int zoneid;
 
                pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page;
-                       unsigned long pfn = pgdat->node_start_pfn + i;
-
-                       if (unlikely(!(i % MAX_ORDER_NR_PAGES)))
-                               touch_nmi_watchdog();
-
-                       if (!pfn_valid(pfn))
+               for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
+                       struct zone *zone = &pgdat->node_zones[zoneid];
+                       if (!populated_zone(zone))
                                continue;
 
-                       page = pfn_to_page(pfn);
-
-                       if (PageHighMem(page))
-                               highmem++;
+                       total += zone->present_pages;
+                       reserved = zone->present_pages - zone->managed_pages;
 
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (page_count(page) == 1)
-                               nonshared++;
-                       else if (page_count(page) > 1)
-                               shared += page_count(page) - 1;
-
-                       total++;
+                       if (is_highmem_idx(zoneid))
+                               highmem += zone->present_pages;
                }
                pgdat_resize_unlock(pgdat, &flags);
        }
 
        printk("%lu pages RAM\n", total);
-#ifdef CONFIG_HIGHMEM
-       printk("%lu pages HighMem\n", highmem);
-#endif
+       printk("%lu pages HighMem/MovableOnly\n", highmem);
        printk("%lu pages reserved\n", reserved);
-       printk("%lu pages shared\n", shared);
-       printk("%lu pages non-shared\n", nonshared);
 #ifdef CONFIG_QUICKLIST
        printk("%lu pages in pagetable cache\n",
                quicklist_total_size());
index 26559bdb4c49737a2d0e33006476f6a9be94385f..48586ac3a62e3691c4950c1c72d904e6ebf036af 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/dcache.h>
+#include <linux/cred.h>
 #include <net/addrconf.h>
 
 #include <asm/page.h>          /* for PAGE_SIZE */
@@ -1218,6 +1219,8 @@ int kptr_restrict __read_mostly;
  *            The maximum supported length is 64 bytes of the input. Consider
  *            to use print_hex_dump() for the larger input.
  * - 'a' For a phys_addr_t type and its derivative types (passed by reference)
+ * - 'd[234]' For a dentry name (optionally 2-4 last components)
+ * - 'D[234]' Same as 'd' but for a struct file
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1312,11 +1315,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                                spec.field_width = default_width;
                        return string(buf, end, "pK-error", spec);
                }
-               if (!((kptr_restrict == 0) ||
-                     (kptr_restrict == 1 &&
-                      has_capability_noaudit(current, CAP_SYSLOG))))
+
+               switch (kptr_restrict) {
+               case 0:
+                       /* Always print %pK values */
+                       break;
+               case 1: {
+                       /*
+                        * Only print the real pointer value if the current
+                        * process has CAP_SYSLOG and is running with the
+                        * same credentials it started with. This is because
+                        * access to files is checked at open() time, but %pK
+                        * checks permission at read() time. We don't want to
+                        * leak pointer values if a binary opens a file using
+                        * %pK and then elevates privileges before reading it.
+                        */
+                       const struct cred *cred = current_cred();
+
+                       if (!has_capability_noaudit(current, CAP_SYSLOG) ||
+                           !uid_eq(cred->euid, cred->uid) ||
+                           !gid_eq(cred->egid, cred->gid))
+                               ptr = NULL;
+                       break;
+               }
+               case 2:
+               default:
+                       /* Always print 0's for %pK */
                        ptr = NULL;
+                       break;
+               }
                break;
+
        case 'N':
                switch (fmt[1]) {
                case 'F':
index 394838f489ebae1b9d00660af54ceac857538653..3f4ffda152bbe9e3ee8b5d2b5e667ce72345e12d 100644 (file)
@@ -153,11 +153,18 @@ config MOVABLE_NODE
        help
          Allow a node to have only movable memory.  Pages used by the kernel,
          such as direct mapping pages cannot be migrated.  So the corresponding
-         memory device cannot be hotplugged.  This option allows users to
-         online all the memory of a node as movable memory so that the whole
-         node can be hotplugged.  Users who don't use the memory hotplug
-         feature are fine with this option on since they don't online memory
-         as movable.
+         memory device cannot be hotplugged.  This option allows the following
+         two things:
+         - When the system is booting, node full of hotpluggable memory can
+         be arranged to have only movable memory so that the whole node can
+         be hot-removed. (need movable_node boot option specified).
+         - After the system is up, the option allows users to online all the
+         memory of a node as movable memory so that the whole node can be
+         hot-removed.
+
+         Users who don't use the memory hotplug feature are fine with this
+         option on since they don't specify movable_node boot option or they
+         don't online memory as movable.
 
          Say Y here if you want to hotplug a whole node.
          Say N here if you want kernel to use memory on all nodes evenly.
index 6ab7744e692ed86cd4417041686dc3a0821cab9f..90bd3507b413b613c6eb0f51b643e2e0fcd615d2 100644 (file)
@@ -172,11 +172,12 @@ void __init free_bootmem_late(unsigned long physaddr, unsigned long size)
 static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 {
        struct page *page;
-       unsigned long start, end, pages, count = 0;
+       unsigned long *map, start, end, pages, count = 0;
 
        if (!bdata->node_bootmem_map)
                return 0;
 
+       map = bdata->node_bootmem_map;
        start = bdata->node_min_pfn;
        end = bdata->node_low_pfn;
 
@@ -184,10 +185,9 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                bdata - bootmem_node_data, start, end);
 
        while (start < end) {
-               unsigned long *map, idx, vec;
+               unsigned long idx, vec;
                unsigned shift;
 
-               map = bdata->node_bootmem_map;
                idx = start - bdata->node_min_pfn;
                shift = idx & (BITS_PER_LONG - 1);
                /*
@@ -784,7 +784,7 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
                return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
        /* update goal according ...MAX_DMA32_PFN */
-       end_pfn = pgdat->node_start_pfn + pgdat->node_spanned_pages;
+       end_pfn = pgdat_end_pfn(pgdat);
 
        if (end_pfn > MAX_DMA32_PFN + (128 >> (20 - PAGE_SHIFT)) &&
            (goal >> PAGE_SHIFT) < MAX_DMA32_PFN) {
index b5326b141a251905a96cd5cd995063a29ca20f91..805165bcd3dd0ab8f27bbff2c9105927ed803c15 100644 (file)
@@ -235,10 +235,9 @@ static bool suitable_migration_target(struct page *page)
 }
 
 /*
- * Isolate free pages onto a private freelist. Caller must hold zone->lock.
- * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
- * pages inside of the pageblock (even though it may still end up isolating
- * some pages).
+ * Isolate free pages onto a private freelist. If @strict is true, will abort
+ * returning 0 on any invalid PFNs or non-free pages inside of the pageblock
+ * (even though it may still end up isolating some pages).
  */
 static unsigned long isolate_freepages_block(struct compact_control *cc,
                                unsigned long blockpfn,
index 2612f60f53ee5a4a22dabc4c9fb132f7bbc537f3..0556c6a44959130e244127183acb9f16b7c3e604 100644 (file)
 #include "internal.h"
 
 /*
- * By default transparent hugepage support is enabled for all mappings
- * and khugepaged scans all mappings. Defrag is only invoked by
- * khugepaged hugepage allocations and by page faults inside
- * MADV_HUGEPAGE regions to avoid the risk of slowing down short lived
- * allocations.
+ * By default transparent hugepage support is disabled in order that avoid
+ * to risk increase the memory footprint of applications without a guaranteed
+ * benefit. When transparent hugepage support is enabled, is for all mappings,
+ * and khugepaged scans all mappings.
+ * Defrag is invoked by khugepaged hugepage allocations and by page faults
+ * for all hugepage allocations.
  */
 unsigned long transparent_hugepage_flags __read_mostly =
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS
@@ -758,14 +759,6 @@ static inline struct page *alloc_hugepage_vma(int defrag,
                               HPAGE_PMD_ORDER, vma, haddr, nd);
 }
 
-#ifndef CONFIG_NUMA
-static inline struct page *alloc_hugepage(int defrag)
-{
-       return alloc_pages(alloc_hugepage_gfpmask(defrag, 0),
-                          HPAGE_PMD_ORDER);
-}
-#endif
-
 static bool set_huge_zero_page(pgtable_t pgtable, struct mm_struct *mm,
                struct vm_area_struct *vma, unsigned long haddr, pmd_t *pmd,
                struct page *zero_page)
@@ -2198,7 +2191,34 @@ static void khugepaged_alloc_sleep(void)
                        msecs_to_jiffies(khugepaged_alloc_sleep_millisecs));
 }
 
+static int khugepaged_node_load[MAX_NUMNODES];
+
 #ifdef CONFIG_NUMA
+static int khugepaged_find_target_node(void)
+{
+       static int last_khugepaged_target_node = NUMA_NO_NODE;
+       int nid, target_node = 0, max_value = 0;
+
+       /* find first node with max normal pages hit */
+       for (nid = 0; nid < MAX_NUMNODES; nid++)
+               if (khugepaged_node_load[nid] > max_value) {
+                       max_value = khugepaged_node_load[nid];
+                       target_node = nid;
+               }
+
+       /* do some balance if several nodes have the same hit record */
+       if (target_node <= last_khugepaged_target_node)
+               for (nid = last_khugepaged_target_node + 1; nid < MAX_NUMNODES;
+                               nid++)
+                       if (max_value == khugepaged_node_load[nid]) {
+                               target_node = nid;
+                               break;
+                       }
+
+       last_khugepaged_target_node = target_node;
+       return target_node;
+}
+
 static bool khugepaged_prealloc_page(struct page **hpage, bool *wait)
 {
        if (IS_ERR(*hpage)) {
@@ -2232,9 +2252,8 @@ static struct page
         * mmap_sem in read mode is good idea also to allow greater
         * scalability.
         */
-       *hpage  = alloc_hugepage_vma(khugepaged_defrag(), vma, address,
-                                     node, __GFP_OTHER_NODE);
-
+       *hpage = alloc_pages_exact_node(node, alloc_hugepage_gfpmask(
+               khugepaged_defrag(), __GFP_OTHER_NODE), HPAGE_PMD_ORDER);
        /*
         * After allocating the hugepage, release the mmap_sem read lock in
         * preparation for taking it in write mode.
@@ -2250,6 +2269,17 @@ static struct page
        return *hpage;
 }
 #else
+static int khugepaged_find_target_node(void)
+{
+       return 0;
+}
+
+static inline struct page *alloc_hugepage(int defrag)
+{
+       return alloc_pages(alloc_hugepage_gfpmask(defrag, 0),
+                          HPAGE_PMD_ORDER);
+}
+
 static struct page *khugepaged_alloc_hugepage(bool *wait)
 {
        struct page *hpage;
@@ -2456,6 +2486,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
        if (pmd_trans_huge(*pmd))
                goto out;
 
+       memset(khugepaged_node_load, 0, sizeof(khugepaged_node_load));
        pte = pte_offset_map_lock(mm, pmd, address, &ptl);
        for (_address = address, _pte = pte; _pte < pte+HPAGE_PMD_NR;
             _pte++, _address += PAGE_SIZE) {
@@ -2472,12 +2503,13 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
                if (unlikely(!page))
                        goto out_unmap;
                /*
-                * Chose the node of the first page. This could
-                * be more sophisticated and look at more pages,
-                * but isn't for now.
+                * Record which node the original page is from and save this
+                * information to khugepaged_node_load[].
+                * Khupaged will allocate hugepage from the node has the max
+                * hit record.
                 */
-               if (node == NUMA_NO_NODE)
-                       node = page_to_nid(page);
+               node = page_to_nid(page);
+               khugepaged_node_load[node]++;
                VM_BUG_ON(PageCompound(page));
                if (!PageLRU(page) || PageLocked(page) || !PageAnon(page))
                        goto out_unmap;
@@ -2492,9 +2524,11 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
                ret = 1;
 out_unmap:
        pte_unmap_unlock(pte, ptl);
-       if (ret)
+       if (ret) {
+               node = khugepaged_find_target_node();
                /* collapse_huge_page will return with the mmap_sem released */
                collapse_huge_page(mm, address, hpage, vma, node);
+       }
 out:
        return ret;
 }
index e126b0ef9ad20023d6a8d3ff505ae71ad96fdaa0..31f01c5011e59414e95b888b2b3d515940ab72ab 100644 (file)
@@ -753,7 +753,9 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
        }
 
        spin_lock_irqsave(&object->lock, flags);
-       if (ptr + size > object->pointer + object->size) {
+       if (size == SIZE_MAX) {
+               size = object->pointer + object->size - ptr;
+       } else if (ptr + size > object->pointer + object->size) {
                kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
                dump_object_info(object);
                kmem_cache_free(scan_area_cache, area);
index 0bea2b262a47837f1c0bd81492e9cfdd30daa041..175fff79dc95749f6607aaa70976ebff09193397 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2309,8 +2309,8 @@ static ssize_t merge_across_nodes_store(struct kobject *kobj,
                         * Allocate stable and unstable together:
                         * MAXSMP NODES_SHIFT 10 will use 16kB.
                         */
-                       buf = kcalloc(nr_node_ids + nr_node_ids,
-                               sizeof(*buf), GFP_KERNEL | __GFP_ZERO);
+                       buf = kcalloc(nr_node_ids + nr_node_ids, sizeof(*buf),
+                                     GFP_KERNEL);
                        /* Let us assume that RB_ROOT is NULL is zero */
                        if (!buf)
                                err = -ENOMEM;
index 0ac412a0a7ee0c68a919754e6b6ae0e40624b30c..53e477bb55587aff585558f91c96a04db9f5c965 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/seq_file.h>
 #include <linux/memblock.h>
 
+#include <asm-generic/sections.h>
+
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
 
@@ -32,6 +34,7 @@ struct memblock memblock __initdata_memblock = {
        .reserved.cnt           = 1,    /* empty dummy entry */
        .reserved.max           = INIT_MEMBLOCK_REGIONS,
 
+       .bottom_up              = false,
        .current_limit          = MEMBLOCK_ALLOC_ANYWHERE,
 };
 
@@ -82,6 +85,73 @@ static long __init_memblock memblock_overlaps_region(struct memblock_type *type,
        return (i < type->cnt) ? i : -1;
 }
 
+/*
+ * __memblock_find_range_bottom_up - find free area utility in bottom-up
+ * @start: start of candidate range
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @size: size of free area to find
+ * @align: alignment of free area to find
+ * @nid: nid of the free area to find, %MAX_NUMNODES for any node
+ *
+ * Utility called from memblock_find_in_range_node(), find free area bottom-up.
+ *
+ * RETURNS:
+ * Found address on success, 0 on failure.
+ */
+static phys_addr_t __init_memblock
+__memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
+                               phys_addr_t size, phys_addr_t align, int nid)
+{
+       phys_addr_t this_start, this_end, cand;
+       u64 i;
+
+       for_each_free_mem_range(i, nid, &this_start, &this_end, NULL) {
+               this_start = clamp(this_start, start, end);
+               this_end = clamp(this_end, start, end);
+
+               cand = round_up(this_start, align);
+               if (cand < this_end && this_end - cand >= size)
+                       return cand;
+       }
+
+       return 0;
+}
+
+/**
+ * __memblock_find_range_top_down - find free area utility, in top-down
+ * @start: start of candidate range
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @size: size of free area to find
+ * @align: alignment of free area to find
+ * @nid: nid of the free area to find, %MAX_NUMNODES for any node
+ *
+ * Utility called from memblock_find_in_range_node(), find free area top-down.
+ *
+ * RETURNS:
+ * Found address on success, 0 on failure.
+ */
+static phys_addr_t __init_memblock
+__memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
+                              phys_addr_t size, phys_addr_t align, int nid)
+{
+       phys_addr_t this_start, this_end, cand;
+       u64 i;
+
+       for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
+               this_start = clamp(this_start, start, end);
+               this_end = clamp(this_end, start, end);
+
+               if (this_end < size)
+                       continue;
+
+               cand = round_down(this_end - size, align);
+               if (cand >= this_start)
+                       return cand;
+       }
+
+       return 0;
+}
+
 /**
  * memblock_find_in_range_node - find free area in given range and node
  * @start: start of candidate range
@@ -92,15 +162,23 @@ static long __init_memblock memblock_overlaps_region(struct memblock_type *type,
  *
  * Find @size free area aligned to @align in the specified range and node.
  *
+ * When allocation direction is bottom-up, the @start should be greater
+ * than the end of the kernel image. Otherwise, it will be trimmed. The
+ * reason is that we want the bottom-up allocation just near the kernel
+ * image so it is highly likely that the allocated memory and the kernel
+ * will reside in the same node.
+ *
+ * If bottom-up allocation failed, will try to allocate memory top-down.
+ *
  * RETURNS:
- * Found address on success, %0 on failure.
+ * Found address on success, 0 on failure.
  */
 phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
                                        phys_addr_t end, phys_addr_t size,
                                        phys_addr_t align, int nid)
 {
-       phys_addr_t this_start, this_end, cand;
-       u64 i;
+       int ret;
+       phys_addr_t kernel_end;
 
        /* pump up @end */
        if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
@@ -109,19 +187,39 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
        /* avoid allocating the first page */
        start = max_t(phys_addr_t, start, PAGE_SIZE);
        end = max(start, end);
+       kernel_end = __pa_symbol(_end);
 
-       for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
-               this_start = clamp(this_start, start, end);
-               this_end = clamp(this_end, start, end);
+       /*
+        * try bottom-up allocation only when bottom-up mode
+        * is set and @end is above the kernel image.
+        */
+       if (memblock_bottom_up() && end > kernel_end) {
+               phys_addr_t bottom_up_start;
 
-               if (this_end < size)
-                       continue;
+               /* make sure we will allocate above the kernel */
+               bottom_up_start = max(start, kernel_end);
 
-               cand = round_down(this_end - size, align);
-               if (cand >= this_start)
-                       return cand;
+               /* ok, try bottom-up allocation first */
+               ret = __memblock_find_range_bottom_up(bottom_up_start, end,
+                                                     size, align, nid);
+               if (ret)
+                       return ret;
+
+               /*
+                * we always limit bottom-up allocation above the kernel,
+                * but top-down allocation doesn't have the limit, so
+                * retrying top-down allocation may succeed when bottom-up
+                * allocation failed.
+                *
+                * bottom-up allocation is expected to be fail very rarely,
+                * so we use WARN_ONCE() here to see the stack trace if
+                * fail happens.
+                */
+               WARN_ONCE(1, "memblock: bottom-up allocation failed, "
+                            "memory hotunplug may be affected\n");
        }
-       return 0;
+
+       return __memblock_find_range_top_down(start, end, size, align, nid);
 }
 
 /**
@@ -134,7 +232,7 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
  * Find @size free area aligned to @align in the specified range.
  *
  * RETURNS:
- * Found address on success, %0 on failure.
+ * Found address on success, 0 on failure.
  */
 phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
                                        phys_addr_t end, phys_addr_t size,
index 796820925de0b758c5eea87a4e3484de07e0e56f..f20a57b7faf2f3bd8faf5b8676ffd7a6adbf7fc7 100644 (file)
@@ -59,6 +59,7 @@
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/tcp_memcontrol.h>
+#include "slab.h"
 
 #include <asm/uaccess.h>
 
@@ -2968,7 +2969,7 @@ static struct kmem_cache *memcg_params_to_cache(struct memcg_cache_params *p)
 
        VM_BUG_ON(p->is_root_cache);
        cachep = p->root_cache;
-       return cachep->memcg_params->memcg_caches[memcg_cache_id(p->memcg)];
+       return cache_from_memcg_idx(cachep, memcg_cache_id(p->memcg));
 }
 
 #ifdef CONFIG_SLABINFO
@@ -2997,21 +2998,14 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size)
        struct res_counter *fail_res;
        struct mem_cgroup *_memcg;
        int ret = 0;
-       bool may_oom;
 
        ret = res_counter_charge(&memcg->kmem, size, &fail_res);
        if (ret)
                return ret;
 
-       /*
-        * Conditions under which we can wait for the oom_killer. Those are
-        * the same conditions tested by the core page allocator
-        */
-       may_oom = (gfp & __GFP_FS) && !(gfp & __GFP_NORETRY);
-
        _memcg = memcg;
        ret = __mem_cgroup_try_charge(NULL, gfp, size >> PAGE_SHIFT,
-                                     &_memcg, may_oom);
+                                     &_memcg, oom_gfp_allowed(gfp));
 
        if (ret == -EINTR)  {
                /*
@@ -3151,7 +3145,7 @@ int memcg_update_cache_size(struct kmem_cache *s, int num_groups)
 {
        struct memcg_cache_params *cur_params = s->memcg_params;
 
-       VM_BUG_ON(s->memcg_params && !s->memcg_params->is_root_cache);
+       VM_BUG_ON(!is_root_cache(s));
 
        if (num_groups > memcg_limited_groups_array_size) {
                int i;
@@ -3412,7 +3406,7 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
        idx = memcg_cache_id(memcg);
 
        mutex_lock(&memcg_cache_mutex);
-       new_cachep = cachep->memcg_params->memcg_caches[idx];
+       new_cachep = cache_from_memcg_idx(cachep, idx);
        if (new_cachep) {
                css_put(&memcg->css);
                goto out;
@@ -3458,8 +3452,8 @@ void kmem_cache_destroy_memcg_children(struct kmem_cache *s)
         * we'll take the set_limit_mutex to protect ourselves against this.
         */
        mutex_lock(&set_limit_mutex);
-       for (i = 0; i < memcg_limited_groups_array_size; i++) {
-               c = s->memcg_params->memcg_caches[i];
+       for_each_memcg_cache_index(i) {
+               c = cache_from_memcg_idx(s, i);
                if (!c)
                        continue;
 
@@ -3592,8 +3586,8 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
         * code updating memcg_caches will issue a write barrier to match this.
         */
        read_barrier_depends();
-       if (likely(cachep->memcg_params->memcg_caches[idx])) {
-               cachep = cachep->memcg_params->memcg_caches[idx];
+       if (likely(cache_from_memcg_idx(cachep, idx))) {
+               cachep = cache_from_memcg_idx(cachep, idx);
                goto out;
        }
 
@@ -5389,45 +5383,50 @@ static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css,
 static int memcg_numa_stat_show(struct cgroup_subsys_state *css,
                                struct cftype *cft, struct seq_file *m)
 {
+       struct numa_stat {
+               const char *name;
+               unsigned int lru_mask;
+       };
+
+       static const struct numa_stat stats[] = {
+               { "total", LRU_ALL },
+               { "file", LRU_ALL_FILE },
+               { "anon", LRU_ALL_ANON },
+               { "unevictable", BIT(LRU_UNEVICTABLE) },
+       };
+       const struct numa_stat *stat;
        int nid;
-       unsigned long total_nr, file_nr, anon_nr, unevictable_nr;
-       unsigned long node_nr;
+       unsigned long nr;
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
-       total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
-       seq_printf(m, "total=%lu", total_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
-       }
-       seq_putc(m, '\n');
-
-       file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
-       seq_printf(m, "file=%lu", file_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               LRU_ALL_FILE);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
-       }
-       seq_putc(m, '\n');
-
-       anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
-       seq_printf(m, "anon=%lu", anon_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               LRU_ALL_ANON);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
+       for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
+               nr = mem_cgroup_nr_lru_pages(memcg, stat->lru_mask);
+               seq_printf(m, "%s=%lu", stat->name, nr);
+               for_each_node_state(nid, N_MEMORY) {
+                       nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
+                                                         stat->lru_mask);
+                       seq_printf(m, " N%d=%lu", nid, nr);
+               }
+               seq_putc(m, '\n');
+       }
+
+       for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
+               struct mem_cgroup *iter;
+
+               nr = 0;
+               for_each_mem_cgroup_tree(iter, memcg)
+                       nr += mem_cgroup_nr_lru_pages(iter, stat->lru_mask);
+               seq_printf(m, "hierarchical_%s=%lu", stat->name, nr);
+               for_each_node_state(nid, N_MEMORY) {
+                       nr = 0;
+                       for_each_mem_cgroup_tree(iter, memcg)
+                               nr += mem_cgroup_node_nr_lru_pages(
+                                       iter, nid, stat->lru_mask);
+                       seq_printf(m, " N%d=%lu", nid, nr);
+               }
+               seq_putc(m, '\n');
        }
-       seq_putc(m, '\n');
 
-       unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
-       seq_printf(m, "unevictable=%lu", unevictable_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               BIT(LRU_UNEVICTABLE));
-               seq_printf(m, " N%d=%lu", nid, node_nr);
-       }
-       seq_putc(m, '\n');
        return 0;
 }
 #endif /* CONFIG_NUMA */
index bf3351b5115e54915a3d7eaa718d10a9771b2c5f..f9d78ec7831f0461549360575d9f779d206bac33 100644 (file)
@@ -1422,19 +1422,6 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
        if (flags & MF_COUNT_INCREASED)
                return 1;
 
-       /*
-        * The lock_memory_hotplug prevents a race with memory hotplug.
-        * This is a big hammer, a better would be nicer.
-        */
-       lock_memory_hotplug();
-
-       /*
-        * Isolate the page, so that it doesn't get reallocated if it
-        * was free. This flag should be kept set until the source page
-        * is freed and PG_hwpoison on it is set.
-        */
-       if (get_pageblock_migratetype(p) != MIGRATE_ISOLATE)
-               set_migratetype_isolate(p, true);
        /*
         * When the target page is a free hugepage, just remove it
         * from free hugepage list.
@@ -1455,7 +1442,6 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags)
                /* Not a free page */
                ret = 1;
        }
-       unlock_memory_hotplug();
        return ret;
 }
 
@@ -1654,15 +1640,28 @@ int soft_offline_page(struct page *page, int flags)
                }
        }
 
+       /*
+        * The lock_memory_hotplug prevents a race with memory hotplug.
+        * This is a big hammer, a better would be nicer.
+        */
+       lock_memory_hotplug();
+
+       /*
+        * Isolate the page, so that it doesn't get reallocated if it
+        * was free. This flag should be kept set until the source page
+        * is freed and PG_hwpoison on it is set.
+        */
+       if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
+               set_migratetype_isolate(page, true);
+
        ret = get_any_page(page, pfn, flags);
-       if (ret < 0)
-               goto unset;
-       if (ret) { /* for in-use pages */
+       unlock_memory_hotplug();
+       if (ret > 0) { /* for in-use pages */
                if (PageHuge(page))
                        ret = soft_offline_huge_page(page, flags);
                else
                        ret = __soft_offline_page(page, flags);
-       } else { /* for free pages */
+       } else if (ret == 0) { /* for free pages */
                if (PageHuge(page)) {
                        set_page_hwpoison_huge_page(hpage);
                        dequeue_hwpoisoned_huge_page(hpage);
@@ -1673,7 +1672,6 @@ int soft_offline_page(struct page *page, int flags)
                        atomic_long_inc(&num_poisoned_pages);
                }
        }
-unset:
        unset_migratetype_isolate(page, MIGRATE_MOVABLE);
        return ret;
 }
index 33a3dbec3cc87bca1ccea07841496897929ed0bd..bf8665849a5fed0b93f6022670c7c571e7eea8c6 100644 (file)
@@ -453,8 +453,6 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
 
 /*
  * This function frees user-level page tables of a process.
- *
- * Must be called with pagetable lock held.
  */
 void free_pgd_range(struct mmu_gather *tlb,
                        unsigned long addr, unsigned long end,
index ed85fe3870e2c5d0094d47c7aa1086084d98235e..489f235502dbdde48f921d998896d78a56b0c1de 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/firmware-map.h>
 #include <linux/stop_machine.h>
 #include <linux/hugetlb.h>
+#include <linux/memblock.h>
 
 #include <asm/tlbflush.h>
 
@@ -365,8 +366,7 @@ out_fail:
 static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn,
                            unsigned long end_pfn)
 {
-       unsigned long old_pgdat_end_pfn =
-               pgdat->node_start_pfn + pgdat->node_spanned_pages;
+       unsigned long old_pgdat_end_pfn = pgdat_end_pfn(pgdat);
 
        if (!pgdat->node_spanned_pages || start_pfn < pgdat->node_start_pfn)
                pgdat->node_start_pfn = start_pfn;
@@ -402,13 +402,12 @@ static int __meminit __add_zone(struct zone *zone, unsigned long phys_start_pfn)
 static int __meminit __add_section(int nid, struct zone *zone,
                                        unsigned long phys_start_pfn)
 {
-       int nr_pages = PAGES_PER_SECTION;
        int ret;
 
        if (pfn_valid(phys_start_pfn))
                return -EEXIST;
 
-       ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages);
+       ret = sparse_add_one_section(zone, phys_start_pfn);
 
        if (ret < 0)
                return ret;
@@ -579,9 +578,9 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn,
 static void shrink_pgdat_span(struct pglist_data *pgdat,
                              unsigned long start_pfn, unsigned long end_pfn)
 {
-       unsigned long pgdat_start_pfn =  pgdat->node_start_pfn;
-       unsigned long pgdat_end_pfn =
-               pgdat->node_start_pfn + pgdat->node_spanned_pages;
+       unsigned long pgdat_start_pfn = pgdat->node_start_pfn;
+       unsigned long p = pgdat_end_pfn(pgdat); /* pgdat_end_pfn namespace clash */
+       unsigned long pgdat_end_pfn = p;
        unsigned long pfn;
        struct mem_section *ms;
        int nid = pgdat->node_id;
@@ -935,7 +934,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        arg.nr_pages = nr_pages;
        node_states_check_changes_online(nr_pages, zone, &arg);
 
-       nid = page_to_nid(pfn_to_page(pfn));
+       nid = pfn_to_nid(pfn);
 
        ret = memory_notify(MEM_GOING_ONLINE, &arg);
        ret = notifier_to_errno(ret);
@@ -1044,17 +1043,23 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
 }
 
 
-/*
+/**
+ * try_online_node - online a node if offlined
+ *
  * called by cpu_up() to online a node without onlined memory.
  */
-int mem_online_node(int nid)
+int try_online_node(int nid)
 {
        pg_data_t       *pgdat;
        int     ret;
 
+       if (node_online(nid))
+               return 0;
+
        lock_memory_hotplug();
        pgdat = hotadd_new_pgdat(nid, 0);
        if (!pgdat) {
+               pr_err("Cannot online node %d due to NULL pgdat\n", nid);
                ret = -ENOMEM;
                goto out;
        }
@@ -1062,6 +1067,12 @@ int mem_online_node(int nid)
        ret = register_one_node(nid);
        BUG_ON(ret);
 
+       if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
+               mutex_lock(&zonelists_mutex);
+               build_all_zonelists(NULL, NULL);
+               mutex_unlock(&zonelists_mutex);
+       }
+
 out:
        unlock_memory_hotplug();
        return ret;
@@ -1412,6 +1423,36 @@ static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
 }
 #endif /* CONFIG_MOVABLE_NODE */
 
+static int __init cmdline_parse_movable_node(char *p)
+{
+#ifdef CONFIG_MOVABLE_NODE
+       /*
+        * Memory used by the kernel cannot be hot-removed because Linux
+        * cannot migrate the kernel pages. When memory hotplug is
+        * enabled, we should prevent memblock from allocating memory
+        * for the kernel.
+        *
+        * ACPI SRAT records all hotpluggable memory ranges. But before
+        * SRAT is parsed, we don't know about it.
+        *
+        * The kernel image is loaded into memory at very early time. We
+        * cannot prevent this anyway. So on NUMA system, we set any
+        * node the kernel resides in as un-hotpluggable.
+        *
+        * Since on modern servers, one node could have double-digit
+        * gigabytes memory, we can assume the memory around the kernel
+        * image is also un-hotpluggable. So before SRAT is parsed, just
+        * allocate memory near the kernel image to try the best to keep
+        * the kernel away from hotpluggable memory.
+        */
+       memblock_set_bottom_up(true);
+#else
+       pr_warn("movable_node option not supported\n");
+#endif
+       return 0;
+}
+early_param("movable_node", cmdline_parse_movable_node);
+
 /* check which state of node_states will be changed when offline memory */
 static void node_states_check_changes_offline(unsigned long nr_pages,
                struct zone *zone, struct memory_notify *arg)
@@ -1702,7 +1743,7 @@ int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-static int is_memblock_offlined_cb(struct memory_block *mem, void *arg)
+static int check_memblock_offlined_cb(struct memory_block *mem, void *arg)
 {
        int ret = !is_memblock_offlined(mem);
 
@@ -1854,7 +1895,7 @@ void __ref remove_memory(int nid, u64 start, u64 size)
         * if this is not the case.
         */
        ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL,
-                               is_memblock_offlined_cb);
+                               check_memblock_offlined_cb);
        if (ret) {
                unlock_memory_hotplug();
                BUG();
index 71cb253368cb72b1bf99d390ca9360ccc277c29b..4cc19f6ab6c6f84da6bb99955f5026a9bc066a76 100644 (file)
@@ -1125,7 +1125,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
        tmp = *from;
        while (!nodes_empty(tmp)) {
                int s,d;
-               int source = -1;
+               int source = NUMA_NO_NODE;
                int dest = 0;
 
                for_each_node_mask(s, tmp) {
@@ -1160,7 +1160,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
                        if (!node_isset(dest, tmp))
                                break;
                }
-               if (source == -1)
+               if (source == NUMA_NO_NODE)
                        break;
 
                node_clear(source, tmp);
@@ -1835,7 +1835,7 @@ static unsigned offset_il_node(struct mempolicy *pol,
        unsigned nnodes = nodes_weight(pol->v.nodes);
        unsigned target;
        int c;
-       int nid = -1;
+       int nid = NUMA_NO_NODE;
 
        if (!nnodes)
                return numa_node_id();
@@ -1872,11 +1872,11 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
 
 /*
  * Return the bit number of a random bit set in the nodemask.
- * (returns -1 if nodemask is empty)
+ * (returns NUMA_NO_NODE if nodemask is empty)
  */
 int node_random(const nodemask_t *maskp)
 {
-       int w, bit = -1;
+       int w, bit = NUMA_NO_NODE;
 
        w = nodes_weight(*maskp);
        if (w)
@@ -2914,62 +2914,45 @@ out:
  * @maxlen:  length of @buffer
  * @pol:  pointer to mempolicy to be formatted
  *
- * Convert a mempolicy into a string.
- * Returns the number of characters in buffer (if positive)
- * or an error (negative)
+ * Convert @pol into a string.  If @buffer is too short, truncate the string.
+ * Recommend a @maxlen of at least 32 for the longest mode, "interleave", the
+ * longest flag, "relative", and to display at least a few node ids.
  */
-int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 {
        char *p = buffer;
-       int l;
-       nodemask_t nodes;
-       unsigned short mode;
-       unsigned short flags = pol ? pol->flags : 0;
-
-       /*
-        * Sanity check:  room for longest mode, flag and some nodes
-        */
-       VM_BUG_ON(maxlen < strlen("interleave") + strlen("relative") + 16);
+       nodemask_t nodes = NODE_MASK_NONE;
+       unsigned short mode = MPOL_DEFAULT;
+       unsigned short flags = 0;
 
-       if (!pol || pol == &default_policy)
-               mode = MPOL_DEFAULT;
-       else
+       if (pol && pol != &default_policy) {
                mode = pol->mode;
+               flags = pol->flags;
+       }
 
        switch (mode) {
        case MPOL_DEFAULT:
-               nodes_clear(nodes);
                break;
-
        case MPOL_PREFERRED:
-               nodes_clear(nodes);
                if (flags & MPOL_F_LOCAL)
                        mode = MPOL_LOCAL;
                else
                        node_set(pol->v.preferred_node, nodes);
                break;
-
        case MPOL_BIND:
-               /* Fall through */
        case MPOL_INTERLEAVE:
                nodes = pol->v.nodes;
                break;
-
        default:
-               return -EINVAL;
+               WARN_ON_ONCE(1);
+               snprintf(p, maxlen, "unknown");
+               return;
        }
 
-       l = strlen(policy_modes[mode]);
-       if (buffer + maxlen < p + l + 1)
-               return -ENOSPC;
-
-       strcpy(p, policy_modes[mode]);
-       p += l;
+       p += snprintf(p, maxlen, policy_modes[mode]);
 
        if (flags & MPOL_MODE_FLAGS) {
-               if (buffer + maxlen < p + 2)
-                       return -ENOSPC;
-               *p++ = '=';
+               p += snprintf(p, buffer + maxlen - p, "=");
 
                /*
                 * Currently, the only defined flags are mutually exclusive
@@ -2981,10 +2964,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
        }
 
        if (!nodes_empty(nodes)) {
-               if (buffer + maxlen < p + 2)
-                       return -ENOSPC;
-               *p++ = ':';
+               p += snprintf(p, buffer + maxlen - p, ":");
                p += nodelist_scnprintf(p, buffer + maxlen - p, nodes);
        }
-       return p - buffer;
 }
index ab199dfc9e26889fbba305ba09b2ab517dd591f7..5a6baddde15d955e72e674e5bd468b9e95eceeb0 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -179,14 +179,12 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
                goto error;
        }
 
-       allowed = (totalram_pages - hugetlb_total_pages())
-               * sysctl_overcommit_ratio / 100;
+       allowed = vm_commit_limit();
        /*
         * Reserve some for root
         */
        if (!cap_sys_admin)
                allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
-       allowed += total_swap_pages;
 
        /*
         * Don't let a single process grow so big a user can't recover
@@ -1856,7 +1854,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct vm_area_struct *vma;
        struct vm_unmapped_area_info info;
 
-       if (len > TASK_SIZE)
+       if (len > TASK_SIZE - mmap_min_addr)
                return -ENOMEM;
 
        if (flags & MAP_FIXED)
@@ -1865,14 +1863,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
-               if (TASK_SIZE - len >= addr &&
+               if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
 
        info.flags = 0;
        info.length = len;
-       info.low_limit = TASK_UNMAPPED_BASE;
+       info.low_limit = mm->mmap_base;
        info.high_limit = TASK_SIZE;
        info.align_mask = 0;
        return vm_unmapped_area(&info);
@@ -1895,7 +1893,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        struct vm_unmapped_area_info info;
 
        /* requested length too big for entire address space */
-       if (len > TASK_SIZE)
+       if (len > TASK_SIZE - mmap_min_addr)
                return -ENOMEM;
 
        if (flags & MAP_FIXED)
@@ -1905,14 +1903,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
-               if (TASK_SIZE - len >= addr &&
+               if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
                                (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
 
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
-       info.low_limit = PAGE_SIZE;
+       info.low_limit = max(PAGE_SIZE, mmap_min_addr);
        info.high_limit = mm->mmap_base;
        info.align_mask = 0;
        addr = vm_unmapped_area(&info);
index a597f2ffcd6fc873a5f5b9779e4e79ac022bb2fe..26667971c824b08ca3dae7188a965e1e4efe0b79 100644 (file)
@@ -112,6 +112,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
        pmd_t *pmd;
        unsigned long next;
        unsigned long pages = 0;
+       unsigned long nr_huge_updates = 0;
 
        pmd = pmd_offset(pud, addr);
        do {
@@ -126,9 +127,10 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                                                newprot, prot_numa);
 
                                if (nr_ptes) {
-                                       if (nr_ptes == HPAGE_PMD_NR)
-                                               pages++;
-
+                                       if (nr_ptes == HPAGE_PMD_NR) {
+                                               pages += HPAGE_PMD_NR;
+                                               nr_huge_updates++;
+                                       }
                                        continue;
                                }
                        }
@@ -141,6 +143,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                pages += this_pages;
        } while (pmd++, addr = next, addr != end);
 
+       if (nr_huge_updates)
+               count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates);
        return pages;
 }
 
index 61107cf55bb3e2c491bffdfb63f489b9587b6f06..2c254d37465549b0230b543cd9ac7c4d60cdf7c1 100644 (file)
@@ -82,27 +82,18 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
 
 static void __init __free_pages_memory(unsigned long start, unsigned long end)
 {
-       unsigned long i, start_aligned, end_aligned;
-       int order = ilog2(BITS_PER_LONG);
+       int order;
 
-       start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
-       end_aligned = end & ~(BITS_PER_LONG - 1);
+       while (start < end) {
+               order = min(MAX_ORDER - 1UL, __ffs(start));
 
-       if (end_aligned <= start_aligned) {
-               for (i = start; i < end; i++)
-                       __free_pages_bootmem(pfn_to_page(i), 0);
+               while (start + (1UL << order) > end)
+                       order--;
 
-               return;
-       }
-
-       for (i = start; i < start_aligned; i++)
-               __free_pages_bootmem(pfn_to_page(i), 0);
+               __free_pages_bootmem(pfn_to_page(start), order);
 
-       for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG)
-               __free_pages_bootmem(pfn_to_page(i), order);
-
-       for (i = end_aligned; i < end; i++)
-               __free_pages_bootmem(pfn_to_page(i), 0);
+               start += (1UL << order);
+       }
 }
 
 static unsigned long __init __free_memory_core(phys_addr_t start,
index 9e6cb02cba644c4ec357775e2acb22c5451f2ee7..fec093adad9c1d65799206805f3d95fe19a1da88 100644 (file)
@@ -1948,13 +1948,12 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
                goto error;
        }
 
-       allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+       allowed = vm_commit_limit();
        /*
         * Reserve some 3% for root
         */
        if (!cap_sys_admin)
                allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
-       allowed += total_swap_pages;
 
        /*
         * Don't let a single process grow so big a user can't recover
index 73d812f16dde6acbad004c8dddb22c140443fcc4..580a5f075ed0ab6e3047351a8271b1f053e35774 100644 (file)
@@ -234,8 +234,8 @@ int page_group_by_mobility_disabled __read_mostly;
 
 void set_pageblock_migratetype(struct page *page, int migratetype)
 {
-
-       if (unlikely(page_group_by_mobility_disabled))
+       if (unlikely(page_group_by_mobility_disabled &&
+                    migratetype < MIGRATE_PCPTYPES))
                migratetype = MIGRATE_UNMOVABLE;
 
        set_pageblock_flags_group(page, (unsigned long)migratetype,
@@ -1027,6 +1027,10 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page,
 {
        int current_order = page_order(page);
 
+       /*
+        * When borrowing from MIGRATE_CMA, we need to release the excess
+        * buddy pages to CMA itself.
+        */
        if (is_migrate_cma(fallback_type))
                return fallback_type;
 
@@ -1091,21 +1095,11 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
                        list_del(&page->lru);
                        rmv_page_order(page);
 
-                       /*
-                        * Borrow the excess buddy pages as well, irrespective
-                        * of whether we stole freepages, or took ownership of
-                        * the pageblock or not.
-                        *
-                        * Exception: When borrowing from MIGRATE_CMA, release
-                        * the excess buddy pages to CMA itself.
-                        */
                        expand(zone, page, order, current_order, area,
-                              is_migrate_cma(migratetype)
-                            ? migratetype : start_migratetype);
+                              new_type);
 
-                       trace_mm_page_alloc_extfrag(page, order,
-                               current_order, start_migratetype, migratetype,
-                               new_type == start_migratetype);
+                       trace_mm_page_alloc_extfrag(page, order, current_order,
+                               start_migratetype, migratetype, new_type);
 
                        return page;
                }
@@ -1711,7 +1705,7 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
  * comments in mmzone.h.  Reduces cache footprint of zonelist scans
  * that have to skip over a lot of full or unallowed zones.
  *
- * If the zonelist cache is present in the passed in zonelist, then
+ * If the zonelist cache is present in the passed zonelist, then
  * returns a pointer to the allowed node mask (either the current
  * tasks mems_allowed, or node_states[N_MEMORY].)
  *
@@ -2593,7 +2587,7 @@ rebalance:
         * running out of options and have to consider going OOM
         */
        if (!did_some_progress) {
-               if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
+               if (oom_gfp_allowed(gfp_mask)) {
                        if (oom_killer_disabled)
                                goto nopage;
                        /* Coredumps can quickly deplete all memory reserves */
@@ -3881,8 +3875,6 @@ static inline unsigned long wait_table_bits(unsigned long size)
        return ffz(~size);
 }
 
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
 /*
  * Check if a pageblock contains reserved pages
  */
@@ -4266,7 +4258,7 @@ static __meminit void zone_pcp_init(struct zone *zone)
         */
        zone->pageset = &boot_pageset;
 
-       if (zone->present_pages)
+       if (populated_zone(zone))
                printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%u\n",
                        zone->name, zone->present_pages,
                                         zone_batchsize(zone));
@@ -5160,7 +5152,7 @@ static void check_for_memory(pg_data_t *pgdat, int nid)
 
        for (zone_type = 0; zone_type <= ZONE_MOVABLE - 1; zone_type++) {
                struct zone *zone = &pgdat->node_zones[zone_type];
-               if (zone->present_pages) {
+               if (populated_zone(zone)) {
                        node_set_state(nid, N_HIGH_MEMORY);
                        if (N_NORMAL_MEMORY != N_HIGH_MEMORY &&
                            zone_type <= ZONE_NORMAL)
index e4ed04149785f069b201cd2ffaa9caa90c4b0d22..7cdbb44aa90bd99bef05f43ee27cc13b2121ed7a 100644 (file)
@@ -401,6 +401,7 @@ ondemand_readahead(struct address_space *mapping,
                   unsigned long req_size)
 {
        unsigned long max = max_sane_readahead(ra->ra_pages);
+       pgoff_t prev_offset;
 
        /*
         * start of file
@@ -452,8 +453,11 @@ ondemand_readahead(struct address_space *mapping,
 
        /*
         * sequential cache miss
+        * trivial case: (offset - prev_offset) == 1
+        * unaligned reads: (offset - prev_offset) == 0
         */
-       if (offset - (ra->prev_pos >> PAGE_CACHE_SHIFT) <= 1UL)
+       prev_offset = (unsigned long long)ra->prev_pos >> PAGE_CACHE_SHIFT;
+       if (offset - prev_offset <= 1UL)
                goto initial_readahead;
 
        /*
@@ -569,7 +573,7 @@ static ssize_t
 do_readahead(struct address_space *mapping, struct file *filp,
             pgoff_t index, unsigned long nr)
 {
-       if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
+       if (!mapping || !mapping->a_ops)
                return -EINVAL;
 
        force_page_cache_readahead(mapping, filp, index, nr);
index 2580db062df97488a92beeb1e008d866db4d7f7e..0c8967bb201878e567c4d949ae1d9ee57cf04d0b 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3982,7 +3982,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
 
        VM_BUG_ON(!mutex_is_locked(&slab_mutex));
        for_each_memcg_cache_index(i) {
-               c = cache_from_memcg(cachep, i);
+               c = cache_from_memcg_idx(cachep, i);
                if (c)
                        /* return value determined by the parent cache only */
                        __do_tune_cpucache(c, limit, batchcount, shared, gfp);
index a535033f7e9a153dfa7252dbb0d74f7be5ae4e58..0859c4241ba10b2ee602eca48af4e34dd82d6ae3 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -160,7 +160,8 @@ static inline const char *cache_name(struct kmem_cache *s)
        return s->name;
 }
 
-static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+static inline struct kmem_cache *
+cache_from_memcg_idx(struct kmem_cache *s, int idx)
 {
        if (!s->memcg_params)
                return NULL;
@@ -204,7 +205,8 @@ static inline const char *cache_name(struct kmem_cache *s)
        return s->name;
 }
 
-static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+static inline struct kmem_cache *
+cache_from_memcg_idx(struct kmem_cache *s, int idx)
 {
        return NULL;
 }
index e2e98af703ea9fdcbab4bcd034bc82a1482c9ca6..0b7bb399b0e46af8ac8b96fbedb67aef413e5cb7 100644 (file)
@@ -571,7 +571,7 @@ memcg_accumulate_slabinfo(struct kmem_cache *s, struct slabinfo *info)
                return;
 
        for_each_memcg_cache_index(i) {
-               c = cache_from_memcg(s, i);
+               c = cache_from_memcg_idx(s, i);
                if (!c)
                        continue;
 
index c3eb3d3ca83565b925e197f2ad44ac2c313345b8..92737a0b787b57b0e5d8467879b50b4915a43f9e 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4983,7 +4983,7 @@ static ssize_t slab_attr_store(struct kobject *kobj,
                 * through the descendants with best-effort propagation.
                 */
                for_each_memcg_cache_index(i) {
-                       struct kmem_cache *c = cache_from_memcg(s, i);
+                       struct kmem_cache *c = cache_from_memcg_idx(s, i);
                        if (c)
                                attribute->store(c, buf, len);
                }
index 4ac1d7ef548f8ce75b65ae64057c300c8b0cc48c..8cc7be0e95906c18068e926490a8509651e3904c 100644 (file)
@@ -590,33 +590,32 @@ void __init sparse_init(void)
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
-                                                unsigned long nr_pages)
+static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid)
 {
        /* This will make the necessary allocations eventually. */
        return sparse_mem_map_populate(pnum, nid);
 }
-static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+static void __kfree_section_memmap(struct page *memmap)
 {
        unsigned long start = (unsigned long)memmap;
-       unsigned long end = (unsigned long)(memmap + nr_pages);
+       unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
 
        vmemmap_free(start, end);
 }
 #ifdef CONFIG_MEMORY_HOTREMOVE
-static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap)
 {
        unsigned long start = (unsigned long)memmap;
-       unsigned long end = (unsigned long)(memmap + nr_pages);
+       unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
 
        vmemmap_free(start, end);
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 #else
-static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
+static struct page *__kmalloc_section_memmap(void)
 {
        struct page *page, *ret;
-       unsigned long memmap_size = sizeof(struct page) * nr_pages;
+       unsigned long memmap_size = sizeof(struct page) * PAGES_PER_SECTION;
 
        page = alloc_pages(GFP_KERNEL|__GFP_NOWARN, get_order(memmap_size));
        if (page)
@@ -634,28 +633,30 @@ got_map_ptr:
        return ret;
 }
 
-static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
-                                                 unsigned long nr_pages)
+static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid)
 {
-       return __kmalloc_section_memmap(nr_pages);
+       return __kmalloc_section_memmap();
 }
 
-static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+static void __kfree_section_memmap(struct page *memmap)
 {
        if (is_vmalloc_addr(memmap))
                vfree(memmap);
        else
                free_pages((unsigned long)memmap,
-                          get_order(sizeof(struct page) * nr_pages));
+                          get_order(sizeof(struct page) * PAGES_PER_SECTION));
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap)
 {
        unsigned long maps_section_nr, removing_section_nr, i;
-       unsigned long magic;
+       unsigned long magic, nr_pages;
        struct page *page = virt_to_page(memmap);
 
+       nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
+               >> PAGE_SHIFT;
+
        for (i = 0; i < nr_pages; i++, page++) {
                magic = (unsigned long) page->lru.next;
 
@@ -684,8 +685,7 @@ static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
  * set.  If this is <=0, then that means that the passed-in
  * map was not consumed and must be freed.
  */
-int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
-                          int nr_pages)
+int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn)
 {
        unsigned long section_nr = pfn_to_section_nr(start_pfn);
        struct pglist_data *pgdat = zone->zone_pgdat;
@@ -702,12 +702,12 @@ int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
        ret = sparse_index_init(section_nr, pgdat->node_id);
        if (ret < 0 && ret != -EEXIST)
                return ret;
-       memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+       memmap = kmalloc_section_memmap(section_nr, pgdat->node_id);
        if (!memmap)
                return -ENOMEM;
        usemap = __kmalloc_section_usemap();
        if (!usemap) {
-               __kfree_section_memmap(memmap, nr_pages);
+               __kfree_section_memmap(memmap);
                return -ENOMEM;
        }
 
@@ -719,7 +719,7 @@ int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
                goto out;
        }
 
-       memset(memmap, 0, sizeof(struct page) * nr_pages);
+       memset(memmap, 0, sizeof(struct page) * PAGES_PER_SECTION);
 
        ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
@@ -729,7 +729,7 @@ out:
        pgdat_resize_unlock(pgdat, &flags);
        if (ret <= 0) {
                kfree(usemap);
-               __kfree_section_memmap(memmap, nr_pages);
+               __kfree_section_memmap(memmap);
        }
        return ret;
 }
@@ -759,7 +759,6 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
 static void free_section_usemap(struct page *memmap, unsigned long *usemap)
 {
        struct page *usemap_page;
-       unsigned long nr_pages;
 
        if (!usemap)
                return;
@@ -771,7 +770,7 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
        if (PageSlab(usemap_page) || PageCompound(usemap_page)) {
                kfree(usemap);
                if (memmap)
-                       __kfree_section_memmap(memmap, PAGES_PER_SECTION);
+                       __kfree_section_memmap(memmap);
                return;
        }
 
@@ -780,12 +779,8 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
         * on the section which has pgdat at boot time. Just keep it as is now.
         */
 
-       if (memmap) {
-               nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
-                       >> PAGE_SHIFT;
-
-               free_map_bootmem(memmap, nr_pages);
-       }
+       if (memmap)
+               free_map_bootmem(memmap);
 }
 
 void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
index de7c904e52e507079f5bae7a2b7854a9d7cf80b0..612a7c9795f6eca1f43f7e86af43d2e74e2f56fa 100644 (file)
@@ -707,7 +707,7 @@ noswap:
        return (swp_entry_t) {0};
 }
 
-/* The only caller of this function is now susupend routine */
+/* The only caller of this function is now suspend routine */
 swp_entry_t get_swap_page_of_type(int type)
 {
        struct swap_info_struct *si;
@@ -845,7 +845,7 @@ static unsigned char swap_entry_free(struct swap_info_struct *p,
 }
 
 /*
- * Caller has made sure that the swapdevice corresponding to entry
+ * Caller has made sure that the swap device corresponding to entry
  * is still around or has not been recycled.
  */
 void swap_free(swp_entry_t entry)
@@ -947,7 +947,7 @@ int try_to_free_swap(struct page *page)
         * original page might be freed under memory pressure, then
         * later read back in from swap, now with the wrong data.
         *
-        * Hibration suspends storage while it is writing the image
+        * Hibernation suspends storage while it is writing the image
         * to disk so check that here.
         */
        if (pm_suspended_storage())
@@ -1179,7 +1179,7 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
         * some architectures (e.g. x86_32 with PAE) we might catch a glimpse
         * of unmatched parts which look like swp_pte, so unuse_pte must
         * recheck under pte lock.  Scanning without pte lock lets it be
-        * preemptible whenever CONFIG_PREEMPT but not CONFIG_HIGHPTE.
+        * preemptable whenever CONFIG_PREEMPT but not CONFIG_HIGHPTE.
         */
        pte = pte_offset_map(pmd, addr);
        do {
@@ -1924,17 +1924,17 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        p->cluster_info = NULL;
        p->flags = 0;
        frontswap_map = frontswap_map_get(p);
-       frontswap_map_set(p, NULL);
        spin_unlock(&p->lock);
        spin_unlock(&swap_lock);
        frontswap_invalidate_area(type);
+       frontswap_map_set(p, NULL);
        mutex_unlock(&swapon_mutex);
        free_percpu(p->percpu_cluster);
        p->percpu_cluster = NULL;
        vfree(swap_map);
        vfree(cluster_info);
        vfree(frontswap_map);
-       /* Destroy swap account informatin */
+       /* Destroy swap account information */
        swap_cgroup_swapoff(type);
 
        inode = mapping->host;
@@ -2786,8 +2786,8 @@ int add_swap_count_continuation(swp_entry_t entry, gfp_t gfp_mask)
 
        /*
         * We are fortunate that although vmalloc_to_page uses pte_offset_map,
-        * no architecture is using highmem pages for kernel pagetables: so it
-        * will not corrupt the GFP_ATOMIC caller's atomic pagetable kmaps.
+        * no architecture is using highmem pages for kernel page tables: so it
+        * will not corrupt the GFP_ATOMIC caller's atomic page table kmaps.
         */
        head = vmalloc_to_page(si->swap_map + offset);
        offset &= ~PAGE_MASK;
index eaf63fc2c92f05078f0c93694ea03b55d425eecb..f7bc2096071cb925bc0e46d83d8156d38179dd0f 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -7,6 +7,9 @@
 #include <linux/security.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
+#include <linux/mman.h>
+#include <linux/hugetlb.h>
+
 #include <asm/uaccess.h>
 
 #include "internal.h"
@@ -398,6 +401,16 @@ struct address_space *page_mapping(struct page *page)
        return mapping;
 }
 
+/*
+ * Committed memory limit enforced when OVERCOMMIT_NEVER policy is used
+ */
+unsigned long vm_commit_limit(void)
+{
+       return ((totalram_pages - hugetlb_total_pages())
+               * sysctl_overcommit_ratio / 100) + total_swap_pages;
+}
+
+
 /* Tracepoints definitions. */
 EXPORT_TRACEPOINT_SYMBOL(kmalloc);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
index 107454312d5ef859ec8dc55f3ba13831cc5cbc65..0fdf96803c5b59623792a24e57015fb0e25098bb 100644 (file)
@@ -359,6 +359,12 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
        if (unlikely(!va))
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * Only scan the relevant parts containing pointers to other objects
+        * to avoid false negatives.
+        */
+       kmemleak_scan_area(&va->rb_node, SIZE_MAX, gfp_mask & GFP_RECLAIM_MASK);
+
 retry:
        spin_lock(&vmap_area_lock);
        /*
@@ -1546,7 +1552,7 @@ static void *__vmalloc_node(unsigned long size, unsigned long align,
                            gfp_t gfp_mask, pgprot_t prot,
                            int node, const void *caller);
 static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
-                                pgprot_t prot, int node, const void *caller)
+                                pgprot_t prot, int node)
 {
        const int order = 0;
        struct page **pages;
@@ -1560,13 +1566,12 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
        /* Please note that the recursion is strictly bounded. */
        if (array_size > PAGE_SIZE) {
                pages = __vmalloc_node(array_size, 1, nested_gfp|__GFP_HIGHMEM,
-                               PAGE_KERNEL, node, caller);
+                               PAGE_KERNEL, node, area->caller);
                area->flags |= VM_VPAGES;
        } else {
                pages = kmalloc_node(array_size, nested_gfp, node);
        }
        area->pages = pages;
-       area->caller = caller;
        if (!area->pages) {
                remove_vm_area(area->addr);
                kfree(area);
@@ -1577,7 +1582,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
                struct page *page;
                gfp_t tmp_mask = gfp_mask | __GFP_NOWARN;
 
-               if (node < 0)
+               if (node == NUMA_NO_NODE)
                        page = alloc_page(tmp_mask);
                else
                        page = alloc_pages_node(node, tmp_mask, order);
@@ -1634,9 +1639,9 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!area)
                goto fail;
 
-       addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+       addr = __vmalloc_area_node(area, gfp_mask, prot, node);
        if (!addr)
-               goto fail;
+               return NULL;
 
        /*
         * In this function, newly allocated vm_struct has VM_UNINITIALIZED
@@ -1646,11 +1651,11 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        clear_vm_uninitialized_flag(area);
 
        /*
-        * A ref_count = 3 is needed because the vm_struct and vmap_area
-        * structures allocated in the __get_vm_area_node() function contain
-        * references to the virtual address of the vmalloc'ed block.
+        * A ref_count = 2 is needed because vm_struct allocated in
+        * __get_vm_area_node() contains a reference to the virtual address of
+        * the vmalloc'ed block.
         */
-       kmemleak_alloc(addr, real_size, 3, gfp_mask);
+       kmemleak_alloc(addr, real_size, 2, gfp_mask);
 
        return addr;
 
@@ -2563,6 +2568,11 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v)
                if (!counters)
                        return;
 
+               /* Pair with smp_wmb() in clear_vm_uninitialized_flag() */
+               smp_rmb();
+               if (v->flags & VM_UNINITIALIZED)
+                       return;
+
                memset(counters, 0, nr_node_ids * sizeof(unsigned int));
 
                for (nr = 0; nr < v->nr_pages; nr++)
@@ -2579,23 +2589,15 @@ static int s_show(struct seq_file *m, void *p)
        struct vmap_area *va = p;
        struct vm_struct *v;
 
-       if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
+       /*
+        * s_show can encounter race with remove_vm_area, !VM_VM_AREA on
+        * behalf of vmap area is being tear down or vm_map_ram allocation.
+        */
+       if (!(va->flags & VM_VM_AREA))
                return 0;
 
-       if (!(va->flags & VM_VM_AREA)) {
-               seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n",
-                       (void *)va->va_start, (void *)va->va_end,
-                                       va->va_end - va->va_start);
-               return 0;
-       }
-
        v = va->vm;
 
-       /* Pair with smp_wmb() in clear_vm_uninitialized_flag() */
-       smp_rmb();
-       if (v->flags & VM_UNINITIALIZED)
-               return 0;
-
        seq_printf(m, "0x%pK-0x%pK %7ld",
                v->addr, v->addr + v->size, v->size);
 
index 9bb314577911f50c06848373d273b3b993373858..72496140ac0843e54c086c18ace843189b47ffda 100644 (file)
@@ -812,6 +812,7 @@ const char * const vmstat_text[] = {
 
 #ifdef CONFIG_NUMA_BALANCING
        "numa_pte_updates",
+       "numa_huge_pte_updates",
        "numa_hint_faults",
        "numa_hint_faults_local",
        "numa_pages_migrated",
@@ -1229,6 +1230,20 @@ static void start_cpu_timer(int cpu)
        schedule_delayed_work_on(cpu, work, __round_jiffies_relative(HZ, cpu));
 }
 
+static void vmstat_cpu_dead(int node)
+{
+       int cpu;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu)
+               if (cpu_to_node(cpu) == node)
+                       goto end;
+
+       node_clear_state(node, N_CPU);
+end:
+       put_online_cpus();
+}
+
 /*
  * Use the cpu notifier to insure that the thresholds are recalculated
  * when necessary.
@@ -1258,6 +1273,7 @@ static int vmstat_cpuup_callback(struct notifier_block *nfb,
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
                refresh_zone_stat_thresholds();
+               vmstat_cpu_dead(cpu_to_node(cpu));
                break;
        default:
                break;
@@ -1276,8 +1292,12 @@ static int __init setup_vmstat(void)
 
        register_cpu_notifier(&vmstat_notifier);
 
-       for_each_online_cpu(cpu)
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
                start_cpu_timer(cpu);
+               node_set_state(cpu_to_node(cpu), N_CPU);
+       }
+       put_online_cpus();
 #endif
 #ifdef CONFIG_PROC_FS
        proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
index d93510c6aa2da860d779570cbf0a4c7cee278ad5..5a63f78a5601aa63112f30b3338be6c413f02f4c 100644 (file)
@@ -217,6 +217,7 @@ static struct zswap_entry *zswap_entry_cache_alloc(gfp_t gfp)
        if (!entry)
                return NULL;
        entry->refcount = 1;
+       RB_CLEAR_NODE(&entry->rbnode);
        return entry;
 }
 
@@ -225,19 +226,6 @@ static void zswap_entry_cache_free(struct zswap_entry *entry)
        kmem_cache_free(zswap_entry_cache, entry);
 }
 
-/* caller must hold the tree lock */
-static void zswap_entry_get(struct zswap_entry *entry)
-{
-       entry->refcount++;
-}
-
-/* caller must hold the tree lock */
-static int zswap_entry_put(struct zswap_entry *entry)
-{
-       entry->refcount--;
-       return entry->refcount;
-}
-
 /*********************************
 * rbtree functions
 **********************************/
@@ -285,6 +273,61 @@ static int zswap_rb_insert(struct rb_root *root, struct zswap_entry *entry,
        return 0;
 }
 
+static void zswap_rb_erase(struct rb_root *root, struct zswap_entry *entry)
+{
+       if (!RB_EMPTY_NODE(&entry->rbnode)) {
+               rb_erase(&entry->rbnode, root);
+               RB_CLEAR_NODE(&entry->rbnode);
+       }
+}
+
+/*
+ * Carries out the common pattern of freeing and entry's zsmalloc allocation,
+ * freeing the entry itself, and decrementing the number of stored pages.
+ */
+static void zswap_free_entry(struct zswap_tree *tree,
+                       struct zswap_entry *entry)
+{
+       zbud_free(tree->pool, entry->handle);
+       zswap_entry_cache_free(entry);
+       atomic_dec(&zswap_stored_pages);
+       zswap_pool_pages = zbud_get_pool_size(tree->pool);
+}
+
+/* caller must hold the tree lock */
+static void zswap_entry_get(struct zswap_entry *entry)
+{
+       entry->refcount++;
+}
+
+/* caller must hold the tree lock
+* remove from the tree and free it, if nobody reference the entry
+*/
+static void zswap_entry_put(struct zswap_tree *tree,
+                       struct zswap_entry *entry)
+{
+       int refcount = --entry->refcount;
+
+       BUG_ON(refcount < 0);
+       if (refcount == 0) {
+               zswap_rb_erase(&tree->rbroot, entry);
+               zswap_free_entry(tree, entry);
+       }
+}
+
+/* caller must hold the tree lock */
+static struct zswap_entry *zswap_entry_find_get(struct rb_root *root,
+                               pgoff_t offset)
+{
+       struct zswap_entry *entry = NULL;
+
+       entry = zswap_rb_search(root, offset);
+       if (entry)
+               zswap_entry_get(entry);
+
+       return entry;
+}
+
 /*********************************
 * per-cpu code
 **********************************/
@@ -368,18 +411,6 @@ static bool zswap_is_full(void)
                zswap_pool_pages);
 }
 
-/*
- * Carries out the common pattern of freeing and entry's zsmalloc allocation,
- * freeing the entry itself, and decrementing the number of stored pages.
- */
-static void zswap_free_entry(struct zswap_tree *tree, struct zswap_entry *entry)
-{
-       zbud_free(tree->pool, entry->handle);
-       zswap_entry_cache_free(entry);
-       atomic_dec(&zswap_stored_pages);
-       zswap_pool_pages = zbud_get_pool_size(tree->pool);
-}
-
 /*********************************
 * writeback code
 **********************************/
@@ -387,7 +418,7 @@ static void zswap_free_entry(struct zswap_tree *tree, struct zswap_entry *entry)
 enum zswap_get_swap_ret {
        ZSWAP_SWAPCACHE_NEW,
        ZSWAP_SWAPCACHE_EXIST,
-       ZSWAP_SWAPCACHE_NOMEM
+       ZSWAP_SWAPCACHE_FAIL,
 };
 
 /*
@@ -401,9 +432,10 @@ enum zswap_get_swap_ret {
  * added to the swap cache, and returned in retpage.
  *
  * If success, the swap cache page is returned in retpage
- * Returns 0 if page was already in the swap cache, page is not locked
- * Returns 1 if the new page needs to be populated, page is locked
- * Returns <0 on error
+ * Returns ZSWAP_SWAPCACHE_EXIST if page was already in the swap cache
+ * Returns ZSWAP_SWAPCACHE_NEW if the new page needs to be populated,
+ *     the new page is added to swapcache and locked
+ * Returns ZSWAP_SWAPCACHE_FAIL on error
  */
 static int zswap_get_swap_cache_page(swp_entry_t entry,
                                struct page **retpage)
@@ -475,7 +507,7 @@ static int zswap_get_swap_cache_page(swp_entry_t entry,
        if (new_page)
                page_cache_release(new_page);
        if (!found_page)
-               return ZSWAP_SWAPCACHE_NOMEM;
+               return ZSWAP_SWAPCACHE_FAIL;
        *retpage = found_page;
        return ZSWAP_SWAPCACHE_EXIST;
 }
@@ -502,7 +534,7 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
        struct page *page;
        u8 *src, *dst;
        unsigned int dlen;
-       int ret, refcount;
+       int ret;
        struct writeback_control wbc = {
                .sync_mode = WB_SYNC_NONE,
        };
@@ -517,23 +549,22 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
 
        /* find and ref zswap entry */
        spin_lock(&tree->lock);
-       entry = zswap_rb_search(&tree->rbroot, offset);
+       entry = zswap_entry_find_get(&tree->rbroot, offset);
        if (!entry) {
                /* entry was invalidated */
                spin_unlock(&tree->lock);
                return 0;
        }
-       zswap_entry_get(entry);
        spin_unlock(&tree->lock);
        BUG_ON(offset != entry->offset);
 
        /* try to allocate swap cache page */
        switch (zswap_get_swap_cache_page(swpentry, &page)) {
-       case ZSWAP_SWAPCACHE_NOMEM: /* no memory */
+       case ZSWAP_SWAPCACHE_FAIL: /* no memory or invalidate happened */
                ret = -ENOMEM;
                goto fail;
 
-       case ZSWAP_SWAPCACHE_EXIST: /* page is unlocked */
+       case ZSWAP_SWAPCACHE_EXIST:
                /* page is already in the swap cache, ignore for now */
                page_cache_release(page);
                ret = -EEXIST;
@@ -556,43 +587,44 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
                SetPageUptodate(page);
        }
 
+       /* move it to the tail of the inactive list after end_writeback */
+       SetPageReclaim(page);
+
        /* start writeback */
        __swap_writepage(page, &wbc, end_swap_bio_write);
        page_cache_release(page);
        zswap_written_back_pages++;
 
        spin_lock(&tree->lock);
-
        /* drop local reference */
-       zswap_entry_put(entry);
-       /* drop the initial reference from entry creation */
-       refcount = zswap_entry_put(entry);
+       zswap_entry_put(tree, entry);
 
        /*
-        * There are three possible values for refcount here:
-        * (1) refcount is 1, load is in progress, unlink from rbtree,
-        *     load will free
-        * (2) refcount is 0, (normal case) entry is valid,
-        *     remove from rbtree and free entry
-        * (3) refcount is -1, invalidate happened during writeback,
-        *     free entry
-        */
-       if (refcount >= 0) {
-               /* no invalidate yet, remove from rbtree */
-               rb_erase(&entry->rbnode, &tree->rbroot);
-       }
+       * There are two possible situations for entry here:
+       * (1) refcount is 1(normal case),  entry is valid and on the tree
+       * (2) refcount is 0, entry is freed and not on the tree
+       *     because invalidate happened during writeback
+       *  search the tree and free the entry if find entry
+       */
+       if (entry == zswap_rb_search(&tree->rbroot, offset))
+               zswap_entry_put(tree, entry);
        spin_unlock(&tree->lock);
-       if (refcount <= 0) {
-               /* free the entry */
-               zswap_free_entry(tree, entry);
-               return 0;
-       }
-       return -EAGAIN;
 
+       goto end;
+
+       /*
+       * if we get here due to ZSWAP_SWAPCACHE_EXIST
+       * a load may happening concurrently
+       * it is safe and okay to not free the entry
+       * if we free the entry in the following put
+       * it it either okay to return !0
+       */
 fail:
        spin_lock(&tree->lock);
-       zswap_entry_put(entry);
+       zswap_entry_put(tree, entry);
        spin_unlock(&tree->lock);
+
+end:
        return ret;
 }
 
@@ -676,11 +708,8 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset,
                if (ret == -EEXIST) {
                        zswap_duplicate_entry++;
                        /* remove from rbtree */
-                       rb_erase(&dupentry->rbnode, &tree->rbroot);
-                       if (!zswap_entry_put(dupentry)) {
-                               /* free */
-                               zswap_free_entry(tree, dupentry);
-                       }
+                       zswap_rb_erase(&tree->rbroot, dupentry);
+                       zswap_entry_put(tree, dupentry);
                }
        } while (ret == -EEXIST);
        spin_unlock(&tree->lock);
@@ -709,17 +738,16 @@ static int zswap_frontswap_load(unsigned type, pgoff_t offset,
        struct zswap_entry *entry;
        u8 *src, *dst;
        unsigned int dlen;
-       int refcount, ret;
+       int ret;
 
        /* find */
        spin_lock(&tree->lock);
-       entry = zswap_rb_search(&tree->rbroot, offset);
+       entry = zswap_entry_find_get(&tree->rbroot, offset);
        if (!entry) {
                /* entry was written back */
                spin_unlock(&tree->lock);
                return -1;
        }
-       zswap_entry_get(entry);
        spin_unlock(&tree->lock);
 
        /* decompress */
@@ -734,22 +762,9 @@ static int zswap_frontswap_load(unsigned type, pgoff_t offset,
        BUG_ON(ret);
 
        spin_lock(&tree->lock);
-       refcount = zswap_entry_put(entry);
-       if (likely(refcount)) {
-               spin_unlock(&tree->lock);
-               return 0;
-       }
+       zswap_entry_put(tree, entry);
        spin_unlock(&tree->lock);
 
-       /*
-        * We don't have to unlink from the rbtree because
-        * zswap_writeback_entry() or zswap_frontswap_invalidate page()
-        * has already done this for us if we are the last reference.
-        */
-       /* free */
-
-       zswap_free_entry(tree, entry);
-
        return 0;
 }
 
@@ -758,7 +773,6 @@ static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
 {
        struct zswap_tree *tree = zswap_trees[type];
        struct zswap_entry *entry;
-       int refcount;
 
        /* find */
        spin_lock(&tree->lock);
@@ -770,20 +784,12 @@ static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
        }
 
        /* remove from rbtree */
-       rb_erase(&entry->rbnode, &tree->rbroot);
+       zswap_rb_erase(&tree->rbroot, entry);
 
        /* drop the initial reference from entry creation */
-       refcount = zswap_entry_put(entry);
+       zswap_entry_put(tree, entry);
 
        spin_unlock(&tree->lock);
-
-       if (refcount) {
-               /* writeback in progress, writeback will free */
-               return;
-       }
-
-       /* free */
-       zswap_free_entry(tree, entry);
 }
 
 /* frees all zswap entries for the given swap type */
@@ -797,11 +803,8 @@ static void zswap_frontswap_invalidate_area(unsigned type)
 
        /* walk the tree and free everything */
        spin_lock(&tree->lock);
-       rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode) {
-               zbud_free(tree->pool, entry->handle);
-               zswap_entry_cache_free(entry);
-               atomic_dec(&zswap_stored_pages);
-       }
+       rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode)
+               zswap_free_entry(tree, entry);
        tree->rbroot = RB_ROOT;
        spin_unlock(&tree->lock);
 
index 66cad506b8a2a944f2873856ef0078445f673b8b..61090e0ff613aefeb5429c26d4efc7775ad97739 100755 (executable)
@@ -241,8 +241,11 @@ our $Sparse        = qr{
                        __ref|
                        __rcu
                }x;
-
-our $InitAttribute = qr{__(?:mem|cpu|dev|net_|)(?:initdata|initconst|init\b)};
+our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
+our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
+our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
+our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
+our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
 
 # Notes to $Attribute:
 # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
@@ -323,7 +326,8 @@ our $logFunctions = qr{(?x:
        (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
        WARN(?:_RATELIMIT|_ONCE|)|
        panic|
-       MODULE_[A-Z_]+
+       MODULE_[A-Z_]+|
+       seq_vprintf|seq_printf|seq_puts
 )};
 
 our $signature_tags = qr{(?xi:
@@ -442,8 +446,9 @@ sub seed_camelcase_file {
                next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
                if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
                        $camelcase{$1} = 1;
-               }
-               elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*\(/) {
+               } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
+                       $camelcase{$1} = 1;
+               } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
                        $camelcase{$1} = 1;
                }
        }
@@ -1512,6 +1517,14 @@ sub rtrim {
        return $string;
 }
 
+sub string_find_replace {
+       my ($string, $find, $replace) = @_;
+
+       $string =~ s/$find/$replace/g;
+
+       return $string;
+}
+
 sub tabify {
        my ($leading) = @_;
 
@@ -1612,6 +1625,8 @@ sub process {
        my @setup_docs = ();
        my $setup_docs = 0;
 
+       my $camelcase_file_seeded = 0;
+
        sanitise_line_reset();
        my $line;
        foreach my $rawline (@rawlines) {
@@ -1754,11 +1769,11 @@ sub process {
                # extract the filename as it passes
                if ($line =~ /^diff --git.*?(\S+)$/) {
                        $realfile = $1;
-                       $realfile =~ s@^([^/]*)/@@;
+                       $realfile =~ s@^([^/]*)/@@ if (!$file);
                        $in_commit_log = 0;
                } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
                        $realfile = $1;
-                       $realfile =~ s@^([^/]*)/@@;
+                       $realfile =~ s@^([^/]*)/@@ if (!$file);
                        $in_commit_log = 0;
 
                        $p1_prefix = $1;
@@ -1947,6 +1962,18 @@ sub process {
                        $rpt_cleaners = 1;
                }
 
+# Check for FSF mailing addresses.
+               if ($rawline =~ /You should have received a copy/ ||
+                   $rawline =~ /write to the Free Software/ ||
+                   $rawline =~ /59 Temple Place/ ||
+                   $rawline =~ /51 Franklin Street/) {
+                       my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+                       my $msg_type = \&ERROR;
+                       $msg_type = \&CHK if ($file);
+                       &{$msg_type}("FSF_MAILING_ADDRESS",
+                               "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
+               }
+
 # check for Kconfig help text having a real description
 # Only applies when adding the entry originally, after that we do not have
 # sufficient context to determine whether it is indeed long enough.
@@ -2838,7 +2865,7 @@ sub process {
                                \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
                                =>|->|<<|>>|<|>|=|!|~|
                                &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
-                               \?|:
+                               \?:|\?|:
                        }x;
                        my @elements = split(/($ops|;)/, $opline);
 
@@ -3061,15 +3088,13 @@ sub process {
                                                $ok = 1;
                                        }
 
-                                       # Ignore ?:
-                                       if (($opv eq ':O' && $ca =~ /\?$/) ||
-                                           ($op eq '?' && $cc =~ /^:/)) {
-                                               $ok = 1;
-                                       }
-
+                                       # messages are ERROR, but ?: are CHK
                                        if ($ok == 0) {
-                                               if (ERROR("SPACING",
-                                                         "spaces required around that '$op' $at\n" . $hereptr)) {
+                                               my $msg_type = \&ERROR;
+                                               $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
+
+                                               if (&{$msg_type}("SPACING",
+                                                                "spaces required around that '$op' $at\n" . $hereptr)) {
                                                        $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
                                                        if (defined $fix_elements[$n + 2]) {
                                                                $fix_elements[$n + 2] =~ s/^\s+//;
@@ -3208,21 +3233,10 @@ sub process {
                }
 
 # Return is not a function.
-               if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
+               if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
                        my $spacing = $1;
-                       my $value = $2;
-
-                       # Flatten any parentheses
-                       $value =~ s/\(/ \(/g;
-                       $value =~ s/\)/\) /g;
-                       while ($value =~ s/\[[^\[\]]*\]/1/ ||
-                              $value !~ /(?:$Ident|-?$Constant)\s*
-                                            $Compare\s*
-                                            (?:$Ident|-?$Constant)/x &&
-                              $value =~ s/\([^\(\)]*\)/1/) {
-                       }
-#print "value<$value>\n";
-                       if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
+                       if ($^V && $^V ge 5.10.0 &&
+                           $stat =~ /^.\s*return\s*$balanced_parens\s*;\s*$/) {
                                ERROR("RETURN_PARENTHESES",
                                      "return is not a function, parentheses are not required\n" . $herecurr);
 
@@ -3231,6 +3245,7 @@ sub process {
                                      "space required before the open parenthesis '('\n" . $herecurr);
                        }
                }
+
 # Return of what appears to be an errno should normally be -'ve
                if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
                        my $name = $1;
@@ -3396,7 +3411,13 @@ sub process {
                                while ($var =~ m{($Ident)}g) {
                                        my $word = $1;
                                        next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
-                                       seed_camelcase_includes() if ($check);
+                                       if ($check) {
+                                               seed_camelcase_includes();
+                                               if (!$file && !$camelcase_file_seeded) {
+                                                       seed_camelcase_file($realfile);
+                                                       $camelcase_file_seeded = 1;
+                                               }
+                                       }
                                        if (!defined $camelcase{$word}) {
                                                $camelcase{$word} = 1;
                                                CHK("CAMELCASE",
@@ -3725,14 +3746,6 @@ sub process {
                        }
                }
 
-sub string_find_replace {
-       my ($string, $find, $replace) = @_;
-
-       $string =~ s/$find/$replace/g;
-
-       return $string;
-}
-
 # check for bad placement of section $InitAttribute (e.g.: __initdata)
                if ($line =~ /(\b$InitAttribute\b)/) {
                        my $attr = $1;
@@ -3751,6 +3764,35 @@ sub string_find_replace {
                        }
                }
 
+# check for $InitAttributeData (ie: __initdata) with const
+               if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
+                       my $attr = $1;
+                       $attr =~ /($InitAttributePrefix)(.*)/;
+                       my $attr_prefix = $1;
+                       my $attr_type = $2;
+                       if (ERROR("INIT_ATTRIBUTE",
+                                 "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$linenr - 1] =~
+                                   s/$InitAttributeData/${attr_prefix}initconst/;
+                       }
+               }
+
+# check for $InitAttributeConst (ie: __initconst) without const
+               if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
+                       my $attr = $1;
+                       if (ERROR("INIT_ATTRIBUTE",
+                                 "Use of $attr requires a separate use of const\n" . $herecurr) &&
+                           $fix) {
+                               my $lead = $fixed[$linenr - 1] =~
+                                   /(^\+\s*(?:static\s+))/;
+                               $lead = rtrim($1);
+                               $lead = "$lead " if ($lead !~ /^\+$/);
+                               $lead = "${lead}const ";
+                               $fixed[$linenr - 1] =~ s/(^\+\s*(?:static\s+))/$lead/;
+                       }
+               }
+
 # prefer usleep_range over udelay
                if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
                        # ignore udelay's < 10, however
@@ -3810,8 +3852,8 @@ sub string_find_replace {
 # check for memory barriers without a comment.
                if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
                        if (!ctx_has_comment($first_line, $linenr)) {
-                               CHK("MEMORY_BARRIER",
-                                   "memory barrier without comment\n" . $herecurr);
+                               WARN("MEMORY_BARRIER",
+                                    "memory barrier without comment\n" . $herecurr);
                        }
                }
 # check of hardware specific defines
@@ -3835,7 +3877,8 @@ sub string_find_replace {
                }
 
 # Check for __inline__ and __inline, prefer inline
-               if ($line =~ /\b(__inline__|__inline)\b/) {
+               if ($realfile !~ m@\binclude/uapi/@ &&
+                   $line =~ /\b(__inline__|__inline)\b/) {
                        if (WARN("INLINE",
                                 "plain inline is preferred over $1\n" . $herecurr) &&
                            $fix) {
@@ -3845,19 +3888,22 @@ sub string_find_replace {
                }
 
 # Check for __attribute__ packed, prefer __packed
-               if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
+               if ($realfile !~ m@\binclude/uapi/@ &&
+                   $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
                        WARN("PREFER_PACKED",
                             "__packed is preferred over __attribute__((packed))\n" . $herecurr);
                }
 
 # Check for __attribute__ aligned, prefer __aligned
-               if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
+               if ($realfile !~ m@\binclude/uapi/@ &&
+                   $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
                        WARN("PREFER_ALIGNED",
                             "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
                }
 
 # Check for __attribute__ format(printf, prefer __printf
-               if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
+               if ($realfile !~ m@\binclude/uapi/@ &&
+                   $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
                        if (WARN("PREFER_PRINTF",
                                 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
                            $fix) {
@@ -3867,7 +3913,8 @@ sub string_find_replace {
                }
 
 # Check for __attribute__ format(scanf, prefer __scanf
-               if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
+               if ($realfile !~ m@\binclude/uapi/@ &&
+                   $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
                        if (WARN("PREFER_SCANF",
                                 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
                            $fix) {
@@ -3903,9 +3950,9 @@ sub string_find_replace {
                }
 
 # check for seq_printf uses that could be seq_puts
-               if ($line =~ /\bseq_printf\s*\(/) {
+               if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
                        my $fmt = get_quoted_string($line, $rawline);
-                       if ($fmt !~ /[^\\]\%/) {
+                       if ($fmt ne "" && $fmt !~ /[^\\]\%/) {
                                if (WARN("PREFER_SEQ_PUTS",
                                         "Prefer seq_puts to seq_printf\n" . $herecurr) &&
                                    $fix) {
@@ -3972,6 +4019,23 @@ sub string_find_replace {
                        }
                }
 
+# check for naked sscanf
+               if ($^V && $^V ge 5.10.0 &&
+                   defined $stat &&
+                   $stat =~ /\bsscanf\b/ &&
+                   ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
+                    $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
+                    $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
+                       my $lc = $stat =~ tr@\n@@;
+                       $lc = $lc + $linenr;
+                       my $stat_real = raw_line($linenr, 0);
+                       for (my $count = $linenr + 1; $count <= $lc; $count++) {
+                               $stat_real = $stat_real . "\n" . raw_line($count, 0);
+                       }
+                       WARN("NAKED_SSCANF",
+                            "unchecked sscanf return value\n" . "$here\n$stat_real\n");
+               }
+
 # check for new externs in .h files.
                if ($realfile =~ /\.h$/ &&
                    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
@@ -4190,6 +4254,12 @@ sub string_find_replace {
                             "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
                }
 
+# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
+               if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
+                       ERROR("DEFINE_ARCH_HAS",
+                             "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
+               }
+
 # check for %L{u,d,i} in strings
                my $string;
                while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
index 4cfdc1797eb8c30d985505838eee6d754b222cbf..2b69eaf5b646e309d95fc9fda3c5a94efce236f6 100644 (file)
@@ -72,6 +72,7 @@ FILELINE * docsection;
 #define FUNCTION      "-function"
 #define NOFUNCTION    "-nofunction"
 #define NODOCSECTIONS "-no-doc-sections"
+#define SHOWNOTFOUND  "-show-not-found"
 
 static char *srctree, *kernsrctree;
 
@@ -294,6 +295,7 @@ static void singfunc(char * filename, char * line)
         int startofsym = 1;
        vec[idx++] = KERNELDOC;
        vec[idx++] = DOCBOOK;
+       vec[idx++] = SHOWNOTFOUND;
 
         /* Split line up in individual parameters preceded by FUNCTION */
         for (i=0; line[i]; i++) {
@@ -325,7 +327,8 @@ static void singfunc(char * filename, char * line)
  */
 static void docsect(char *filename, char *line)
 {
-       char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */
+       /* kerneldoc -docbook -show-not-found -function "section" file NULL */
+       char *vec[7];
        char *s;
 
        for (s = line; *s; s++)
@@ -341,10 +344,11 @@ static void docsect(char *filename, char *line)
 
        vec[0] = KERNELDOC;
        vec[1] = DOCBOOK;
-       vec[2] = FUNCTION;
-       vec[3] = line;
-       vec[4] = filename;
-       vec[5] = NULL;
+       vec[2] = SHOWNOTFOUND;
+       vec[3] = FUNCTION;
+       vec[4] = line;
+       vec[5] = filename;
+       vec[6] = NULL;
        exec_kernel_doc(vec);
 }
 
index b482f162a18af48e6e83f6097581a317d64b194f..ef474098d9f1d1e2609221d3d3571c1f29d1b599 100644 (file)
@@ -240,12 +240,24 @@ case "$arg" in
                output_file="$1"
                cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
                output=${cpio_list}
-               echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
-               echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
-               echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
-               echo "$output_file" | grep -q "\.xz$" && \
-                               compr="xz --check=crc32 --lzma2=dict=1MiB"
-               echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
+               echo "$output_file" | grep -q "\.gz$" \
+                && [ -x "`which gzip 2> /dev/null`" ] \
+                && compr="gzip -n -9 -f"
+               echo "$output_file" | grep -q "\.bz2$" \
+                && [ -x "`which bzip2 2> /dev/null`" ] \
+                && compr="bzip2 -9 -f"
+               echo "$output_file" | grep -q "\.lzma$" \
+                && [ -x "`which lzma 2> /dev/null`" ] \
+                && compr="lzma -9 -f"
+               echo "$output_file" | grep -q "\.xz$" \
+                && [ -x "`which xz 2> /dev/null`" ] \
+                && compr="xz --check=crc32 --lzma2=dict=1MiB"
+               echo "$output_file" | grep -q "\.lzo$" \
+                && [ -x "`which lzop 2> /dev/null`" ] \
+                && compr="lzop -9 -f"
+               echo "$output_file" | grep -q "\.lz4$" \
+                && [ -x "`which lz4 2> /dev/null`" ] \
+                && compr="lz4 -9 -f"
                echo "$output_file" | grep -q "\.cpio$" && compr="cat"
                shift
                ;;
index 4305b2f2ec5eb7f8432c2c6dd7daf983b59f6d24..dbd3e1ebbdada403bb5074669494428791ea2ba3 100755 (executable)
@@ -257,6 +257,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
                'July', 'August', 'September', 'October',
                'November', 'December')[(localtime)[4]] .
   " " . ((localtime)[5]+1900);
+my $show_not_found = 0;
 
 # Essentially these are globals.
 # They probably want to be tidied up, made more localised or something.
@@ -369,6 +370,8 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        usage();
     } elsif ($cmd eq '-no-doc-sections') {
            $no_doc_sections = 1;
+    } elsif ($cmd eq '-show-not-found') {
+       $show_not_found = 1;
     }
 }
 
@@ -2536,6 +2539,9 @@ sub process_file($) {
     }
     if ($initial_section_counter == $section_counter) {
        print STDERR "Warning(${file}): no structured comments found\n";
+       if (($function_only == 1) && ($show_not_found == 1)) {
+           print STDERR "    Was looking for '$_'.\n" for keys %function_table;
+       }
        if ($output_mode eq "xml") {
            # The template wants at least one RefEntry here; make one.
            print "<refentry>\n";
index 8247979e8f64dd2eef5671544d3b39e8ed3487fc..bfcea5d3b27d35d64a57990bba8a6be3d9f0feed 100644 (file)
@@ -599,18 +599,17 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
        else
                export = export_from_sec(info, get_secindex(info, sym));
 
+       /* CRC'd symbol */
+       if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+               crc = (unsigned int) sym->st_value;
+               sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
+                               export);
+       }
+
        switch (sym->st_shndx) {
        case SHN_COMMON:
                warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
                break;
-       case SHN_ABS:
-               /* CRC'd symbol */
-               if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
-                       crc = (unsigned int) sym->st_value;
-                       sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
-                                       export);
-               }
-               break;
        case SHN_UNDEF:
                /* undefined symbol */
                if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
index 7c2310c5b996dee9d43df56574b30236342c3c81..5f7a8b663cb9c9eb59b32f4ce63076a6a86914cc 100644 (file)
@@ -152,6 +152,30 @@ static void (*w2)(uint16_t, uint16_t *);
 
 typedef void (*table_sort_t)(char *, int);
 
+/*
+ * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+ * the way to -256..-1, to avoid conflicting with real section
+ * indices.
+ */
+#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
+
+static inline int is_shndx_special(unsigned int i)
+{
+       return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(unsigned int shndx,
+                                       unsigned int sym_offs,
+                                       const Elf32_Word *symtab_shndx_start)
+{
+       if (is_shndx_special(shndx))
+               return SPECIAL(shndx);
+       if (shndx != SHN_XINDEX)
+               return shndx;
+       return r(&symtab_shndx_start[sym_offs]);
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "sortextable.h"
 #define SORTEXTABLE_64
index f5eb43d429267f5bfeeaf0c27eab24e2e07f0f84..8fac3fd697a6ec34c4908ca60386f2dee3c29bb0 100644 (file)
@@ -98,6 +98,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
        Elf_Shdr *symtab_sec = NULL;
        Elf_Shdr *extab_sec = NULL;
        Elf_Sym *sym;
+       const Elf_Sym *symtab;
+       Elf32_Word *symtab_shndx_start = NULL;
        Elf_Sym *sort_needed_sym;
        Elf_Shdr *sort_needed_sec;
        Elf_Rel *relocs = NULL;
@@ -109,11 +111,22 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
        int extab_index = 0;
        int i;
        int idx;
+       unsigned int num_sections;
+       unsigned int secindex_strings;
 
        shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
-       shstrtab_sec = shdr + r2(&ehdr->e_shstrndx);
+
+       num_sections = r2(&ehdr->e_shnum);
+       if (num_sections == SHN_UNDEF)
+               num_sections = _r(&shdr[0].sh_size);
+
+       secindex_strings = r2(&ehdr->e_shstrndx);
+       if (secindex_strings == SHN_XINDEX)
+               secindex_strings = r(&shdr[0].sh_link);
+
+       shstrtab_sec = shdr + secindex_strings;
        secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
-       for (i = 0; i < r2(&ehdr->e_shnum); i++) {
+       for (i = 0; i < num_sections; i++) {
                idx = r(&shdr[i].sh_name);
                if (strcmp(secstrtab + idx, "__ex_table") == 0) {
                        extab_sec = shdr + i;
@@ -129,6 +142,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
                        symtab_sec = shdr + i;
                if (strcmp(secstrtab + idx, ".strtab") == 0)
                        strtab_sec = shdr + i;
+               if (r(&shdr[i].sh_type) == SHT_SYMTAB_SHNDX)
+                       symtab_shndx_start = (Elf32_Word *)(
+                               (const char *)ehdr + _r(&shdr[i].sh_offset));
        }
        if (strtab_sec == NULL) {
                fprintf(stderr, "no .strtab in  file: %s\n", fname);
@@ -138,6 +154,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
                fprintf(stderr, "no .symtab in  file: %s\n", fname);
                fail_file();
        }
+       symtab = (const Elf_Sym *)((const char *)ehdr +
+                                  _r(&symtab_sec->sh_offset));
        if (extab_sec == NULL) {
                fprintf(stderr, "no __ex_table in  file: %s\n", fname);
                fail_file();
@@ -176,7 +194,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
                        fname);
                fail_file();
        }
-       sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)];
+       sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
+                                            sort_needed_sym - symtab,
+                                            symtab_shndx_start)];
        sort_done_location = (void *)ehdr +
                _r(&sort_needed_sec->sh_offset) +
                _r(&sort_needed_sym->st_value) -
index 8460edce1c3b6b5cc90dff481e5588c75e2285ad..443e9e599a7583c0992162084cec77bd2b4b102a 100644 (file)
@@ -267,10 +267,9 @@ static int allocate_sram(struct snd_pcm_substream *substream,
                return 0;
 
        ppcm->period_bytes_max = size;
-       iram_virt = (void *)gen_pool_alloc(sram_pool, size);
+       iram_virt = gen_pool_dma_alloc(sram_pool, size, &iram_phys);
        if (!iram_virt)
                goto exit1;
-       iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
        iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
        if (!iram_dma)
                goto exit2;
index 8235e231d89c013dd957f08b3336a0d3d3a941e4..7929e19b0ef5970b1942da441770df909f29629e 100644 (file)
@@ -201,10 +201,9 @@ static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream,
        if (!gpool)
                return -ENOMEM;
 
-       buf->area = (unsigned char *)gen_pool_alloc(gpool, size);
+       buf->area = gen_pool_dma_alloc(gpool, size, &buf->addr);
        if (!buf->area)
                return -ENOMEM;
-       buf->addr = gen_pool_virt_to_phys(gpool, (unsigned long)buf->area);
        buf->bytes = size;
        return 0;
 }
index 71c9c2511ee71eef150f8d8da86dd10713b84e9f..d5e9d6d185c82f7ff087b51a54300421508edeca 100644 (file)
 #define PM_PSHIFT_BITS      6
 #define PM_PSHIFT_OFFSET    (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
 #define PM_PSHIFT_MASK      (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
-#define PM_PSHIFT(x)        (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
+#define __PM_PSHIFT(x)      (((uint64_t) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
 #define PM_PFRAME_MASK      ((1LL << PM_PSHIFT_OFFSET) - 1)
 #define PM_PFRAME(x)        ((x) & PM_PFRAME_MASK)
 
+#define __PM_SOFT_DIRTY      (1LL)
 #define PM_PRESENT          PM_STATUS(4LL)
 #define PM_SWAP             PM_STATUS(2LL)
+#define PM_SOFT_DIRTY       __PM_PSHIFT(__PM_SOFT_DIRTY)
 
 
 /*
@@ -83,6 +85,7 @@
 #define KPF_OWNER_PRIVATE      37
 #define KPF_ARCH               38
 #define KPF_UNCACHED           39
+#define KPF_SOFTDIRTY          40
 
 /* [48-] take some arbitrary free slots for expanding overloaded flags
  * not part of kernel API
@@ -132,6 +135,7 @@ static const char * const page_flag_names[] = {
        [KPF_OWNER_PRIVATE]     = "O:owner_private",
        [KPF_ARCH]              = "h:arch",
        [KPF_UNCACHED]          = "c:uncached",
+       [KPF_SOFTDIRTY]         = "f:softdirty",
 
        [KPF_READAHEAD]         = "I:readahead",
        [KPF_SLOB_FREE]         = "P:slob_free",
@@ -417,7 +421,7 @@ static int bit_mask_ok(uint64_t flags)
        return 1;
 }
 
-static uint64_t expand_overloaded_flags(uint64_t flags)
+static uint64_t expand_overloaded_flags(uint64_t flags, uint64_t pme)
 {
        /* SLOB/SLUB overload several page flags */
        if (flags & BIT(SLAB)) {
@@ -433,6 +437,9 @@ static uint64_t expand_overloaded_flags(uint64_t flags)
        if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
                flags ^= BIT(RECLAIM) | BIT(READAHEAD);
 
+       if (pme & PM_SOFT_DIRTY)
+               flags |= BIT(SOFTDIRTY);
+
        return flags;
 }
 
@@ -448,11 +455,11 @@ static uint64_t well_known_flags(uint64_t flags)
        return flags;
 }
 
-static uint64_t kpageflags_flags(uint64_t flags)
+static uint64_t kpageflags_flags(uint64_t flags, uint64_t pme)
 {
-       flags = expand_overloaded_flags(flags);
-
-       if (!opt_raw)
+       if (opt_raw)
+               flags = expand_overloaded_flags(flags, pme);
+       else
                flags = well_known_flags(flags);
 
        return flags;
@@ -545,9 +552,9 @@ static size_t hash_slot(uint64_t flags)
 }
 
 static void add_page(unsigned long voffset,
-                    unsigned long offset, uint64_t flags)
+                    unsigned long offset, uint64_t flags, uint64_t pme)
 {
-       flags = kpageflags_flags(flags);
+       flags = kpageflags_flags(flags, pme);
 
        if (!bit_mask_ok(flags))
                return;
@@ -569,7 +576,8 @@ static void add_page(unsigned long voffset,
 #define KPAGEFLAGS_BATCH       (64 << 10)      /* 64k pages */
 static void walk_pfn(unsigned long voffset,
                     unsigned long index,
-                    unsigned long count)
+                    unsigned long count,
+                    uint64_t pme)
 {
        uint64_t buf[KPAGEFLAGS_BATCH];
        unsigned long batch;
@@ -583,7 +591,7 @@ static void walk_pfn(unsigned long voffset,
                        break;
 
                for (i = 0; i < pages; i++)
-                       add_page(voffset + i, index + i, buf[i]);
+                       add_page(voffset + i, index + i, buf[i], pme);
 
                index += pages;
                count -= pages;
@@ -608,7 +616,7 @@ static void walk_vma(unsigned long index, unsigned long count)
                for (i = 0; i < pages; i++) {
                        pfn = pagemap_pfn(buf[i]);
                        if (pfn)
-                               walk_pfn(index + i, pfn, 1);
+                               walk_pfn(index + i, pfn, 1, buf[i]);
                }
 
                index += pages;
@@ -659,7 +667,7 @@ static void walk_addr_ranges(void)
 
        for (i = 0; i < nr_addr_ranges; i++)
                if (!opt_pid)
-                       walk_pfn(0, opt_offset[i], opt_size[i]);
+                       walk_pfn(0, opt_offset[i], opt_size[i], 0);
                else
                        walk_task(opt_offset[i], opt_size[i]);
 
index 029ffe6cd0d8c309404b81626d1ee5d7f62ce1a0..e767f019accfa6a90374a270056739d09e93b920 100644 (file)
@@ -6,20 +6,23 @@ klibcdirs:;
 PHONY += klibcdirs
 
 
-# Gzip
-suffix_$(CONFIG_INITRAMFS_COMPRESSION_GZIP)   = .gz
-
 # Bzip2
-suffix_$(CONFIG_INITRAMFS_COMPRESSION_BZIP2)  = .bz2
+suffix_$(CONFIG_RD_BZIP2)  = .bz2
 
 # Lzma
-suffix_$(CONFIG_INITRAMFS_COMPRESSION_LZMA)   = .lzma
+suffix_$(CONFIG_RD_LZMA)   = .lzma
 
 # XZ
-suffix_$(CONFIG_INITRAMFS_COMPRESSION_XZ)     = .xz
+suffix_$(CONFIG_RD_XZ)     = .xz
 
 # Lzo
-suffix_$(CONFIG_INITRAMFS_COMPRESSION_LZO)   = .lzo
+suffix_$(CONFIG_RD_LZO)    = .lzo
+
+# Lz4
+suffix_$(CONFIG_RD_LZ4)    = .lz4
+
+# Gzip
+suffix_$(CONFIG_RD_GZIP)   = .gz
 
 AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/initramfs_data.cpio$(suffix_y)"
 
@@ -53,7 +56,10 @@ endif
 quiet_cmd_initfs = GEN     $@
       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 
-targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio.xz initramfs_data.cpio.lzo initramfs_data.cpio
+targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 \
+       initramfs_data.cpio.lzma initramfs_data.cpio.xz \
+       initramfs_data.cpio.lzo initramfs_data.cpio.lz4 \
+       initramfs_data.cpio
 # do not try to update files included in initramfs
 $(deps_initramfs): ;
 
@@ -66,4 +72,3 @@ $(deps_initramfs): klibcdirs
 $(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
        $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d
        $(call if_changed,initfs)
-
index af8c925e93ebd4536e41897c5fcfff10f3fffda8..225ad244cf8833371543c6fb3f0f2df8d54b48dc 100644 (file)
@@ -382,24 +382,15 @@ error:
 static char *cpio_replace_env(char *new_location)
 {
        char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var),
-                               PATH_MAX - strlen(expanded));
-                       strncat(expanded, end + 1,
-                               PATH_MAX - strlen(expanded));
-                       strncpy(new_location, expanded, PATH_MAX);
-                       new_location[PATH_MAX] = 0;
-               } else
-                       break;
+       char *start, *end, *var;
+
+       while ((start = strstr(new_location, "${")) &&
+              (end = strchr(start + 2, '}'))) {
+               *start = *end = 0;
+               var = getenv(start + 2);
+               snprintf(expanded, sizeof expanded, "%s%s%s",
+                        new_location, var ? var : "", end + 1);
+               strcpy(new_location, expanded);
        }
 
        return new_location;