Merge branch 'akpm' (aka "Andrew's patch-bomb")
Linus Torvalds [Wed, 11 Jan 2012 00:42:48 +0000 (16:42 -0800)]
Andrew elucidates:
 - First installmeant of MM.  We have a HUGE number of MM patches this
   time.  It's crazy.
 - MAINTAINERS updates
 - backlight updates
 - leds
 - checkpatch updates
 - misc ELF stuff
 - rtc updates
 - reiserfs
 - procfs
 - some misc other bits

* akpm: (124 commits)
  user namespace: make signal.c respect user namespaces
  workqueue: make alloc_workqueue() take printf fmt and args for name
  procfs: add hidepid= and gid= mount options
  procfs: parse mount options
  procfs: introduce the /proc/<pid>/map_files/ directory
  procfs: make proc_get_link to use dentry instead of inode
  signal: add block_sigmask() for adding sigmask to current->blocked
  sparc: make SA_NOMASK a synonym of SA_NODEFER
  reiserfs: don't lock root inode searching
  reiserfs: don't lock journal_init()
  reiserfs: delay reiserfs lock until journal initialization
  reiserfs: delete comments referring to the BKL
  drivers/rtc/interface.c: fix alarm rollover when day or month is out-of-range
  drivers/rtc/rtc-twl.c: add DT support for RTC inside twl4030/twl6030
  drivers/rtc/: remove redundant spi driver bus initialization
  drivers/rtc/rtc-jz4740.c: make jz4740_rtc_driver static
  drivers/rtc/rtc-mc13xxx.c: make mc13xxx_rtc_idtable static
  rtc: convert drivers/rtc/* to use module_platform_driver()
  drivers/rtc/rtc-wm831x.c: convert to devm_kzalloc()
  drivers/rtc/rtc-wm831x.c: remove unused period IRQ handler
  ...

166 files changed:
Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/twl-rtc.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/kernel-parameters.txt
Documentation/trace/events-kmem.txt
Documentation/trace/postprocess/trace-pagealloc-postprocess.pl
Documentation/trace/tracepoint-analysis.txt
MAINTAINERS
arch/arm/Kconfig
arch/mips/Kconfig
arch/sparc/include/asm/signal.h
arch/x86/Kconfig
arch/x86/kernel/signal.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-88pm860x.c
drivers/leds/leds-adp5520.c
drivers/leds/leds-ams-delta.c
drivers/leds/leds-asic3.c
drivers/leds/leds-atmel-pwm.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-cobalt-qube.c
drivers/leds/leds-da903x.c
drivers/leds/leds-dac124s085.c
drivers/leds/leds-fsg.c
drivers/leds/leds-gpio.c
drivers/leds/leds-hp6xx.c
drivers/leds/leds-lm3530.c
drivers/leds/leds-lp3944.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lt3593.c
drivers/leds/leds-mc13783.c
drivers/leds/leds-netxbig.c
drivers/leds/leds-ns2.c
drivers/leds/leds-pca9532.c
drivers/leds/leds-pca955x.c
drivers/leds/leds-pwm.c
drivers/leds/leds-rb532.c
drivers/leds/leds-regulator.c
drivers/leds/leds-renesas-tpu.c
drivers/leds/leds-s3c24xx.c
drivers/leds/leds-tca6507.c [new file with mode: 0644]
drivers/leds/leds-wm831x-status.c
drivers/leds/leds-wm8350.c
drivers/rtc/interface.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-bq4802.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-dm355evm.c
drivers/rtc/rtc-ds1286.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-jz4740.c
drivers/rtc/rtc-lpc32xx.c
drivers/rtc/rtc-m41t93.c
drivers/rtc/rtc-m41t94.c
drivers/rtc/rtc-m48t35.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6902.c
drivers/rtc/rtc-max8925.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pcf50633.c
drivers/rtc/rtc-pm8xxx.c
drivers/rtc/rtc-rs5c348.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-stk17ta8.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-twl.c
drivers/rtc/rtc-v3020.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-vt8500.c
drivers/rtc/rtc-wm831x.c
drivers/rtc/rtc-wm8350.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/adp5520_bl.c
drivers/video/backlight/adx_bl.c [deleted file]
drivers/video/backlight/backlight.c
drivers/video/backlight/da903x_bl.c
drivers/video/backlight/ep93xx_bl.c
drivers/video/backlight/generic_bl.c
drivers/video/backlight/jornada720_bl.c
drivers/video/backlight/jornada720_lcd.c
drivers/video/backlight/lcd.c
drivers/video/backlight/ld9040.c
drivers/video/backlight/max8925_bl.c
drivers/video/backlight/omap1_bl.c
drivers/video/backlight/pcf50633-backlight.c
drivers/video/backlight/platform_lcd.c
drivers/video/backlight/pwm_bl.c
drivers/video/backlight/wm831x_bl.c
fs/Kconfig.binfmt
fs/binfmt_elf.c
fs/btrfs/file.c
fs/exec.c
fs/inode.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/root.c
fs/reiserfs/bitmap.c
fs/reiserfs/journal.c
fs/reiserfs/super.c
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/gfp.h
include/linux/kernel.h
include/linux/leds-tca6507.h [new file with mode: 0644]
include/linux/mempolicy.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/page-debug-flags.h
include/linux/pagevec.h
include/linux/pid_namespace.h
include/linux/proc_fs.h
include/linux/rmap.h
include/linux/signal.h
include/linux/swap.h
include/linux/workqueue.h
include/linux/writeback.h
include/trace/events/kmem.h
include/trace/events/oom.h [new file with mode: 0644]
include/trace/events/task.h [new file with mode: 0644]
ipc/mqueue.c
kernel/fork.c
kernel/power/snapshot.c
kernel/signal.c
kernel/workqueue.c
lib/btree.c
lib/crc32.c
mm/Kconfig.debug
mm/bootmem.c
mm/compaction.c
mm/fadvise.c
mm/filemap.c
mm/hugetlb.c
mm/mempolicy.c
mm/mempool.c
mm/migrate.c
mm/mmap.c
mm/mremap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/rmap.c
mm/slub.c
mm/swap.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
scripts/checkpatch.pl
scripts/get_maintainer.pl
tools/perf/Documentation/examples.txt

diff --git a/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration b/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
new file mode 100644 (file)
index 0000000..4cf1e72
--- /dev/null
@@ -0,0 +1,12 @@
+What:           Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
+Date:           Oct 2011
+KernelVersion:  3.0
+Contact:        Mark Godfrey <mark.godfrey@stericsson.com>
+Description:    The rtc_calibration attribute allows the userspace to
+                calibrate the AB8500.s 32KHz Real Time Clock.
+                Every 60 seconds the AB8500 will correct the RTC's value
+                by adding to it the value of this attribute.
+                The range of the attribute is -127 to +127 in units of
+                30.5 micro-seconds (half-parts-per-million of the 32KHz clock)
+Users:          The /vendor/st-ericsson/base_utilities/core/rtc_calibration
+                daemon uses this interface.
diff --git a/Documentation/devicetree/bindings/rtc/twl-rtc.txt b/Documentation/devicetree/bindings/rtc/twl-rtc.txt
new file mode 100644 (file)
index 0000000..596e0c9
--- /dev/null
@@ -0,0 +1,12 @@
+* TI twl RTC
+
+The TWL family (twl4030/6030) contains a RTC.
+
+Required properties:
+- compatible : Should be twl4030-rtc
+
+Examples:
+
+rtc@0 {
+    compatible = "ti,twl4030-rtc";
+};
index 0ec91f0..12fee13 100644 (file)
@@ -41,6 +41,8 @@ Table of Contents
   3.5  /proc/<pid>/mountinfo - Information about mounts
   3.6  /proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
 
+  4    Configuring procfs
+  4.1  Mount options
 
 ------------------------------------------------------------------------------
 Preface
@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value
 is limited in size compared to the cmdline value, so writing anything longer
 then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
 comm value.
+
+
+------------------------------------------------------------------------------
+Configuring procfs
+------------------------------------------------------------------------------
+
+4.1    Mount options
+---------------------
+
+The following mount options are supported:
+
+       hidepid=        Set /proc/<pid>/ access mode.
+       gid=            Set the group authorized to learn processes information.
+
+hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
+(default).
+
+hidepid=1 means users may not access any /proc/<pid>/ directories but their
+own.  Sensitive files like cmdline, sched*, status are now protected against
+other users.  This makes it impossible to learn whether any user runs
+specific program (given the program doesn't reveal itself by its behaviour).
+As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users,
+poorly written programs passing sensitive information via program arguments are
+now protected against local eavesdroppers.
+
+hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other
+users.  It doesn't mean that it hides a fact whether a process with a specific
+pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"),
+but it hides process' uid and gid, which may be learned by stat()'ing
+/proc/<pid>/ otherwise.  It greatly complicates an intruder's task of gathering
+information about running processes, whether some daemon runs with elevated
+privileges, whether other user runs some sensitive program, whether other users
+run any program at all, etc.
+
+gid= defines a group authorized to learn processes information otherwise
+prohibited by hidepid=.  If you use some daemon like identd which needs to learn
+information about processes information, just add identd to this group.
index 73baff1..c92b153 100644 (file)
@@ -628,6 +628,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        no_debug_objects
                        [KNL] Disable object debugging
 
+       debug_guardpage_minorder=
+                       [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
+                       parameter allows control of the order of pages that will
+                       be intentionally kept free (and hence protected) by the
+                       buddy allocator. Bigger value increase the probability
+                       of catching random memory corruption, but reduce the
+                       amount of memory for normal system use. The maximum
+                       possible value is MAX_ORDER/2.  Setting this parameter
+                       to 1 or 2 should be enough to identify most random
+                       memory corruption problems caused by bugs in kernel or
+                       driver code when a CPU writes to (or reads from) a
+                       random memory location. Note that there exists a class
+                       of memory corruptions problems caused by buggy H/W or
+                       F/W or by drivers badly programing DMA (basically when
+                       memory is written at bus level and the CPU MMU is
+                       bypassed) which are not detectable by
+                       CONFIG_DEBUG_PAGEALLOC, hence this option will not help
+                       tracking down these problems.
+
        debugpat        [X86] Enable PAT debugging
 
        decnet.addr=    [HW,NET]
index aa82ee4..1948004 100644 (file)
@@ -40,8 +40,8 @@ but the call_site can usually be used to extrapolate that information.
 ==================
 mm_page_alloc            page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s
 mm_page_alloc_zone_locked page=%p pfn=%lu order=%u migratetype=%d cpu=%d percpu_refill=%d
-mm_page_free_direct      page=%p pfn=%lu order=%d
-mm_pagevec_free                  page=%p pfn=%lu order=%d cold=%d
+mm_page_free             page=%p pfn=%lu order=%d
+mm_page_free_batched     page=%p pfn=%lu order=%d cold=%d
 
 These four events deal with page allocation and freeing. mm_page_alloc is
 a simple indicator of page allocator activity. Pages may be allocated from
@@ -53,13 +53,13 @@ amounts of activity imply high activity on the zone->lock. Taking this lock
 impairs performance by disabling interrupts, dirtying cache lines between
 CPUs and serialising many CPUs.
 
-When a page is freed directly by the caller, the mm_page_free_direct event
+When a page is freed directly by the caller, the only mm_page_free event
 is triggered. Significant amounts of activity here could indicate that the
 callers should be batching their activities.
 
-When pages are freed using a pagevec, the mm_pagevec_free is
-triggered. Broadly speaking, pages are taken off the LRU lock in bulk and
-freed in batch with a pagevec. Significant amounts of activity here could
+When pages are freed in batch, the also mm_page_free_batched is triggered.
+Broadly speaking, pages are taken off the LRU lock in bulk and
+freed in batch with a page list. Significant amounts of activity here could
 indicate that the system is under memory pressure and can also indicate
 contention on the zone->lru_lock.
 
index 7df50e8..0a120aa 100644 (file)
@@ -17,8 +17,8 @@ use Getopt::Long;
 
 # Tracepoint events
 use constant MM_PAGE_ALLOC             => 1;
-use constant MM_PAGE_FREE_DIRECT       => 2;
-use constant MM_PAGEVEC_FREE           => 3;
+use constant MM_PAGE_FREE              => 2;
+use constant MM_PAGE_FREE_BATCHED      => 3;
 use constant MM_PAGE_PCPU_DRAIN                => 4;
 use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5;
 use constant MM_PAGE_ALLOC_EXTFRAG     => 6;
@@ -223,10 +223,10 @@ EVENT_PROCESS:
                # Perl Switch() sucks majorly
                if ($tracepoint eq "mm_page_alloc") {
                        $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++;
-               } elsif ($tracepoint eq "mm_page_free_direct") {
-                       $perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT}++;
-               } elsif ($tracepoint eq "mm_pagevec_free") {
-                       $perprocesspid{$process_pid}->{MM_PAGEVEC_FREE}++;
+               } elsif ($tracepoint eq "mm_page_free") {
+                       $perprocesspid{$process_pid}->{MM_PAGE_FREE}++
+               } elsif ($tracepoint eq "mm_page_free_batched") {
+                       $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}++;
                } elsif ($tracepoint eq "mm_page_pcpu_drain") {
                        $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++;
                        $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++;
@@ -336,8 +336,8 @@ sub dump_stats {
                        $process_pid,
                        $stats{$process_pid}->{MM_PAGE_ALLOC},
                        $stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED},
-                       $stats{$process_pid}->{MM_PAGE_FREE_DIRECT},
-                       $stats{$process_pid}->{MM_PAGEVEC_FREE},
+                       $stats{$process_pid}->{MM_PAGE_FREE},
+                       $stats{$process_pid}->{MM_PAGE_FREE_BATCHED},
                        $stats{$process_pid}->{MM_PAGE_PCPU_DRAIN},
                        $stats{$process_pid}->{HIGH_PCPU_DRAINS},
                        $stats{$process_pid}->{HIGH_PCPU_REFILLS},
@@ -364,8 +364,8 @@ sub aggregate_perprocesspid() {
 
                $perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC};
                $perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED};
-               $perprocess{$process}->{MM_PAGE_FREE_DIRECT} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT};
-               $perprocess{$process}->{MM_PAGEVEC_FREE} += $perprocesspid{$process_pid}->{MM_PAGEVEC_FREE};
+               $perprocess{$process}->{MM_PAGE_FREE} += $perprocesspid{$process_pid}->{MM_PAGE_FREE};
+               $perprocess{$process}->{MM_PAGE_FREE_BATCHED} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED};
                $perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN};
                $perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS};
                $perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS};
index 87bee3c..058cc6c 100644 (file)
@@ -93,14 +93,14 @@ By specifying the -a switch and analysing sleep, the system-wide events
 for a duration of time can be examined.
 
  $ perf stat -a \
-       -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
-       -e kmem:mm_pagevec_free \
+       -e kmem:mm_page_alloc -e kmem:mm_page_free \
+       -e kmem:mm_page_free_batched \
        sleep 10
  Performance counter stats for 'sleep 10':
 
            9630  kmem:mm_page_alloc
-           2143  kmem:mm_page_free_direct
-           7424  kmem:mm_pagevec_free
+           2143  kmem:mm_page_free
+           7424  kmem:mm_page_free_batched
 
    10.002577764  seconds time elapsed
 
@@ -119,15 +119,15 @@ basis using set_ftrace_pid.
 Events can be activated and tracked for the duration of a process on a local
 basis using PCL such as follows.
 
-  $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
-                -e kmem:mm_pagevec_free ./hackbench 10
+  $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \
+                -e kmem:mm_page_free_batched ./hackbench 10
   Time: 0.909
 
     Performance counter stats for './hackbench 10':
 
           17803  kmem:mm_page_alloc
-          12398  kmem:mm_page_free_direct
-           4827  kmem:mm_pagevec_free
+          12398  kmem:mm_page_free
+           4827  kmem:mm_page_free_batched
 
     0.973913387  seconds time elapsed
 
@@ -146,8 +146,8 @@ to know what the standard deviation is. By and large, this is left to the
 performance analyst to do it by hand. In the event that the discrete event
 occurrences are useful to the performance analyst, then perf can be used.
 
-  $ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free_direct
-                       -e kmem:mm_pagevec_free ./hackbench 10
+  $ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free
+                       -e kmem:mm_page_free_batched ./hackbench 10
   Time: 0.890
   Time: 0.895
   Time: 0.915
@@ -157,8 +157,8 @@ occurrences are useful to the performance analyst, then perf can be used.
    Performance counter stats for './hackbench 10' (5 runs):
 
           16630  kmem:mm_page_alloc         ( +-   3.542% )
-          11486  kmem:mm_page_free_direct   ( +-   4.771% )
-           4730  kmem:mm_pagevec_free       ( +-   2.325% )
+          11486  kmem:mm_page_free         ( +-   4.771% )
+           4730  kmem:mm_page_free_batched  ( +-   2.325% )
 
     0.982653002  seconds time elapsed   ( +-   1.448% )
 
@@ -168,15 +168,15 @@ aggregation of discrete events, then a script would need to be developed.
 Using --repeat, it is also possible to view how events are fluctuating over
 time on a system-wide basis using -a and sleep.
 
-  $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
-               -e kmem:mm_pagevec_free \
+  $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \
+               -e kmem:mm_page_free_batched \
                -a --repeat 10 \
                sleep 1
   Performance counter stats for 'sleep 1' (10 runs):
 
            1066  kmem:mm_page_alloc         ( +-  26.148% )
-            182  kmem:mm_page_free_direct   ( +-   5.464% )
-            890  kmem:mm_pagevec_free       ( +-  30.079% )
+            182  kmem:mm_page_free          ( +-   5.464% )
+            890  kmem:mm_page_free_batched  ( +-  30.079% )
 
     1.002251757  seconds time elapsed   ( +-   0.005% )
 
@@ -220,8 +220,8 @@ were generating events within the kernel. To begin this sort of analysis, the
 data must be recorded. At the time of writing, this required root:
 
   $ perf record -c 1 \
-       -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
-       -e kmem:mm_pagevec_free \
+       -e kmem:mm_page_alloc -e kmem:mm_page_free \
+       -e kmem:mm_page_free_batched \
        ./hackbench 10
   Time: 0.894
   [ perf record: Captured and wrote 0.733 MB perf.data (~32010 samples) ]
@@ -260,8 +260,8 @@ noticed that X was generating an insane amount of page allocations so let's look
 at it:
 
   $ perf record -c 1 -f \
-               -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \
-               -e kmem:mm_pagevec_free \
+               -e kmem:mm_page_alloc -e kmem:mm_page_free \
+               -e kmem:mm_page_free_batched \
                -p `pidof X`
 
 This was interrupted after a few seconds and
index a2883a2..0460f65 100644 (file)
@@ -342,7 +342,7 @@ S:  Supported
 F:     drivers/mfd/adp5520.c
 F:     drivers/video/backlight/adp5520_bl.c
 F:     drivers/leds/leds-adp5520.c
-F:     drivers/gpio/adp5520-gpio.c
+F:     drivers/gpio/gpio-adp5520.c
 F:     drivers/input/keyboard/adp5520-keys.c
 
 ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
@@ -351,7 +351,7 @@ L:  device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/ADP5588
 S:     Supported
 F:     drivers/input/keyboard/adp5588-keys.c
-F:     drivers/gpio/adp5588-gpio.c
+F:     drivers/gpio/gpio-adp5588.c
 
 ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
 M:     Michael Hennerich <michael.hennerich@analog.com>
@@ -914,7 +914,6 @@ M:  Lennert Buytenhek <kernel@wantstofly.org>
 M:     Nicolas Pitre <nico@fluxnic.net>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Odd Fixes
-F:     arch/arm/mach-loki/
 F:     arch/arm/mach-kirkwood/
 F:     arch/arm/mach-mv78xx0/
 F:     arch/arm/mach-orion5x/
@@ -1076,8 +1075,8 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-s5pv210/mach-aquila.c
 F:     arch/arm/mach-s5pv210/mach-goni.c
-F:     arch/arm/mach-exynos4/mach-universal_c210.c
-F:     arch/arm/mach-exynos4/mach-nuri.c
+F:     arch/arm/mach-exynos/mach-universal_c210.c
+F:     arch/arm/mach-exynos/mach-nuri.c
 
 ARM/SAMSUNG S5P SERIES FIMC SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -1105,7 +1104,6 @@ M:        Tomasz Stanislawski <t.stanislaws@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     arch/arm/plat-s5p/dev-tv.c
 F:     drivers/media/video/s5p-tv/
 
 ARM/SHMOBILE ARM ARCHITECTURE
@@ -1140,14 +1138,13 @@ L:      linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.mcuos.com
 S:     Maintained
 F:     arch/arm/mach-w90x900/
-F:     arch/arm/mach-nuc93x/
 F:     drivers/input/keyboard/w90p910_keypad.c
 F:     drivers/input/touchscreen/w90p910_ts.c
 F:     drivers/watchdog/nuc900_wdt.c
 F:     drivers/net/ethernet/nuvoton/w90p910_ether.c
 F:     drivers/mtd/nand/nuc900_nand.c
 F:     drivers/rtc/rtc-nuc900.c
-F:     drivers/spi/spi_nuc900.c
+F:     drivers/spi/spi-nuc900.c
 F:     drivers/usb/host/ehci-w90x900.c
 F:     drivers/video/nuc900fb.c
 
@@ -1172,7 +1169,6 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-ux500/
 F:     drivers/dma/ste_dma40*
-F:     drivers/mfd/ab3550*
 F:     drivers/mfd/abx500*
 F:     drivers/mfd/ab8500*
 F:     drivers/mfd/stmpe*
@@ -1352,7 +1348,7 @@ F:        drivers/net/ethernet/cadence/
 ATMEL SPI DRIVER
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
-F:     drivers/spi/atmel_spi.*
+F:     drivers/spi/spi-atmel.*
 
 ATMEL USBA UDC DRIVER
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -1491,7 +1487,7 @@ M:        Sonic Zhang <sonic.zhang@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
-F:     drivers/tty/serial/bfin_5xx.c
+F:     drivers/tty/serial/bfin_uart.c
 
 BLACKFIN WATCHDOG DRIVER
 M:     Mike Frysinger <vapier.adi@gmail.com>
@@ -1621,7 +1617,7 @@ BT8XXGPIO DRIVER
 M:     Michael Buesch <m@bues.ch>
 W:     http://bu3sch.de/btgpio.php
 S:     Maintained
-F:     drivers/gpio/bt8xxgpio.c
+F:     drivers/gpio/gpio-bt8xx.c
 
 BTRFS FILE SYSTEM
 M:     Chris Mason <chris.mason@oracle.com>
@@ -1662,7 +1658,7 @@ L:        linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     Documentation/video4linux/cafe_ccic
-F:     drivers/media/video/cafe_ccic*
+F:     drivers/media/video/marvell-ccic/
 
 CAIF NETWORK LAYER
 M:     Sjur Braendeland <sjur.brandeland@stericsson.com>
@@ -2100,7 +2096,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
 L:     netdev@vger.kernel.org
 S:     Orphan
 F:     Documentation/networking/dmfe.txt
-F:     drivers/net/ethernet/tulip/dmfe.c
+F:     drivers/net/ethernet/dec/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
 M:     Kurt Garloff <garloff@suse.de>
@@ -2173,6 +2169,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
 F:     drivers/usb/dwc3/
 
+DEVICE FREQUENCY (DEVFREQ)
+M:     MyungJoo Ham <myungjoo.ham@samsung.com>
+M:     Kyungmin Park <kyungmin.park@samsung.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     drivers/devfreq/
+
 DEVICE NUMBER REGISTRY
 M:     Torben Mathiasen <device@lanana.org>
 W:     http://lanana.org/docs/device-list/index.html
@@ -2910,7 +2913,7 @@ GRETH 10/100/1G Ethernet MAC device driver
 M:     Kristoffer Glembo <kristoffer@gaisler.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/greth*
+F:     drivers/net/ethernet/aeroflex/
 
 GSPCA FINEPIX SUBDRIVER
 M:     Frank Zago <frank@zago.net>
@@ -3860,8 +3863,7 @@ L:        keyrings@linux-nfs.org
 S:     Supported
 F:     Documentation/security/keys-trusted-encrypted.txt
 F:     include/keys/encrypted-type.h
-F:     security/keys/encrypted.c
-F:     security/keys/encrypted.h
+F:     security/keys/encrypted-keys/
 
 KGDB / KDB /debug_core
 M:     Jason Wessel <jason.wessel@windriver.com>
@@ -5313,7 +5315,7 @@ T:        git git://git.linaro.org/people/ycmiao/pxa-linux.git
 S:     Maintained
 F:     arch/arm/mach-pxa/
 F:     drivers/pcmcia/pxa2xx*
-F:     drivers/spi/pxa2xx*
+F:     drivers/spi/spi-pxa2xx*
 F:     drivers/usb/gadget/pxa2*
 F:     include/sound/pxa2xx-lib.h
 F:     sound/arm/pxa*
@@ -5795,13 +5797,14 @@ L:      linux-mmc@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
 S:     Maintained
 F:     drivers/mmc/host/sdhci.*
+F:     drivers/mmc/host/sdhci-pltfm.[ch]
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
 M:     Anton Vorontsov <avorontsov@ru.mvista.com>
 L:     linuxppc-dev@lists.ozlabs.org
 L:     linux-mmc@vger.kernel.org
 S:     Maintained
-F:     drivers/mmc/host/sdhci-of.*
+F:     drivers/mmc/host/sdhci-pltfm.[ch]
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
 M:     Ben Dooks <ben-linux@fluff.org>
@@ -6180,9 +6183,7 @@ M:        Viresh Kumar <viresh.kumar@st.com>
 W:     http://www.st.com/spear
 S:     Maintained
 F:     arch/arm/mach-spear*/clock.c
-F:     arch/arm/mach-spear*/include/mach/clkdev.h
 F:     arch/arm/plat-spear/clock.c
-F:     arch/arm/plat-spear/include/plat/clkdev.h
 F:     arch/arm/plat-spear/include/plat/clock.h
 
 SPEAR PAD MULTIPLEXING SUPPORT
@@ -6306,7 +6307,7 @@ STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
 M:     Jarod Wilson <jarod@wilsonet.com>
 W:     http://www.lirc.org/
 S:     Odd Fixes
-F:     drivers/staging/lirc/
+F:     drivers/staging/media/lirc/
 
 STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
 M:     Julian Andres Klode <jak@jak-linux.org>
@@ -6342,7 +6343,7 @@ F:        drivers/staging/sm7xx/
 STAGING - SOFTLOGIC 6x10 MPEG CODEC
 M:     Ben Collins <bcollins@bluecherry.net>
 S:     Odd Fixes
-F:     drivers/staging/solo6x10/
+F:     drivers/staging/media/solo6x10/
 
 STAGING - SPEAKUP CONSOLE SPEECH DRIVER
 M:     William Hubbs <w.d.hubbs@gmail.com>
@@ -6645,7 +6646,7 @@ TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ethernet/tulip/
+F:     drivers/net/ethernet/dec/tulip/
 
 TUN/TAP driver
 M:     Maxim Krasnyansky <maxk@qualcomm.com>
index 9d66dfc..98a6459 100644 (file)
@@ -16,6 +16,7 @@ config ARM
        select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
        select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
        select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
+       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
index a7636d3..c529cfe 100644 (file)
@@ -16,6 +16,7 @@ config MIPS
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_KPROBES
        select HAVE_KRETPROBES
+       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_DMA_ATTRS
index e49b828..aa42fe3 100644 (file)
@@ -143,10 +143,11 @@ struct sigstack {
 #define SA_ONSTACK     _SV_SSTACK
 #define SA_RESTART     _SV_INTR
 #define SA_ONESHOT     _SV_RESET
-#define SA_NOMASK      0x20u
+#define SA_NODEFER     0x20u
 #define SA_NOCLDWAIT    0x100u
 #define SA_SIGINFO      0x200u
 
+#define SA_NOMASK      SA_NODEFER
 
 #define SIG_BLOCK          0x01        /* for blocking signals */
 #define SIG_UNBLOCK        0x02        /* for unblocking signals */
index 1d2a69d..d6ddc0b 100644 (file)
@@ -62,6 +62,7 @@ config X86
        select ANON_INODES
        select HAVE_ARCH_KMEMCHECK
        select HAVE_USER_RETURN_NOTIFIER
+       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
index 54ddaeb..46a01bd 100644 (file)
@@ -682,7 +682,6 @@ static int
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                struct pt_regs *regs)
 {
-       sigset_t blocked;
        int ret;
 
        /* Are we from a system call? */
@@ -733,10 +732,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
         */
        regs->flags &= ~X86_EFLAGS_TF;
 
-       sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&blocked, sig);
-       set_current_blocked(&blocked);
+       block_sigmask(ka, sig);
 
        tracehook_signal_handler(sig, info, ka, regs,
                                 test_thread_flag(TIF_SINGLESTEP));
index 1b75a56..897a77d 100644 (file)
@@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU
          pin function. The latter to support brightness control.
          Brightness control is supported but hardware blinking is not.
 
+config LEDS_TCA6507
+       tristate "LED Support for TCA6507 I2C chip"
+       depends on LEDS_CLASS && I2C
+       help
+         This option enables support for LEDs connected to TC6507
+         LED driver chips accessed via the I2C bus.
+         Driver support brightness control and hardware-assisted blinking.
+
 config LEDS_TRIGGERS
        bool "LED Trigger support"
        depends on LEDS_CLASS
index e4f6bf5..5c9dc4b 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO)                       += leds-gpio.o
 obj-$(CONFIG_LEDS_LP3944)              += leds-lp3944.o
 obj-$(CONFIG_LEDS_LP5521)              += leds-lp5521.o
 obj-$(CONFIG_LEDS_LP5523)              += leds-lp5523.o
+obj-$(CONFIG_LEDS_TCA6507)             += leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
 obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
index 0810604..4ca0062 100644 (file)
@@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = {
        .remove = pm860x_led_remove,
 };
 
-static int __devinit pm860x_led_init(void)
-{
-       return platform_driver_register(&pm860x_led_driver);
-}
-module_init(pm860x_led_init);
-
-static void __devexit pm860x_led_exit(void)
-{
-       platform_driver_unregister(&pm860x_led_driver);
-}
-module_exit(pm860x_led_exit);
+module_platform_driver(pm860x_led_driver);
 
 MODULE_DESCRIPTION("LED driver for Marvell PM860x");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index 7ba4c7b..b1400db 100644 (file)
@@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = {
        .remove         = __devexit_p(adp5520_led_remove),
 };
 
-static int __init adp5520_led_init(void)
-{
-       return platform_driver_register(&adp5520_led_driver);
-}
-module_init(adp5520_led_init);
-
-static void __exit adp5520_led_exit(void)
-{
-       platform_driver_unregister(&adp5520_led_driver);
-}
-module_exit(adp5520_led_exit);
+module_platform_driver(adp5520_led_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
index 8c00937..0742835 100644 (file)
@@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = {
        },
 };
 
-static int __init ams_delta_led_init(void)
-{
-       return platform_driver_register(&ams_delta_led_driver);
-}
-
-static void __exit ams_delta_led_exit(void)
-{
-       platform_driver_unregister(&ams_delta_led_driver);
-}
-
-module_init(ams_delta_led_init);
-module_exit(ams_delta_led_exit);
+module_platform_driver(ams_delta_led_driver);
 
 MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
 MODULE_DESCRIPTION("Amstrad Delta LED driver");
index 48d9fe6..525a924 100644 (file)
@@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = {
        },
 };
 
-MODULE_ALIAS("platform:leds-asic3");
-
-static int __init asic3_led_init(void)
-{
-       return platform_driver_register(&asic3_led_driver);
-}
-
-static void __exit asic3_led_exit(void)
-{
-       platform_driver_unregister(&asic3_led_driver);
-}
-
-module_init(asic3_led_init);
-module_exit(asic3_led_exit);
+module_platform_driver(asic3_led_driver);
 
 MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
 MODULE_DESCRIPTION("HTC ASIC3 LED driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-asic3");
index 109c875..800243b 100644 (file)
@@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev)
        return 0;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:leds-atmel-pwm");
-
 static struct platform_driver pwmled_driver = {
        .driver = {
                .name =         "leds-atmel-pwm",
                .owner =        THIS_MODULE,
        },
        /* REVISIT add suspend() and resume() methods */
+       .probe =        pwmled_probe,
        .remove =       __exit_p(pwmled_remove),
 };
 
-static int __init modinit(void)
-{
-       return platform_driver_probe(&pwmled_driver, pwmled_probe);
-}
-module_init(modinit);
-
-static void __exit modexit(void)
-{
-       platform_driver_unregister(&pwmled_driver);
-}
-module_exit(modexit);
+module_platform_driver(pwmled_driver);
 
 MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-atmel-pwm");
index ea21855..591cbdf 100644 (file)
@@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
        i2c_set_clientdata(client, led);
 
        /* Configure RESET GPIO (L: RESET, H: RESET cancel) */
-       gpio_request(pdata->reset_gpio, "RGB_RESETB");
-       gpio_direction_output(pdata->reset_gpio, 1);
+       gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB");
 
        /* Tacss = min 0.1ms */
        udelay(100);
@@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = {
        .id_table       = bd2802_id,
 };
 
-static int __init bd2802_init(void)
-{
-       return i2c_add_driver(&bd2802_i2c_driver);
-}
-module_init(bd2802_init);
-
-static void __exit bd2802_exit(void)
-{
-       i2c_del_driver(&bd2802_i2c_driver);
-}
-module_exit(bd2802_exit);
+module_i2c_driver(bd2802_i2c_driver);
 
 MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
 MODULE_DESCRIPTION("BD2802 LED driver");
index da5fb01..6a8725c 100644 (file)
@@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
        return 0;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:cobalt-qube-leds");
-
 static struct platform_driver cobalt_qube_led_driver = {
        .probe  = cobalt_qube_led_probe,
        .remove = __devexit_p(cobalt_qube_led_remove),
@@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = {
        },
 };
 
-static int __init cobalt_qube_led_init(void)
-{
-       return platform_driver_register(&cobalt_qube_led_driver);
-}
-
-static void __exit cobalt_qube_led_exit(void)
-{
-       platform_driver_unregister(&cobalt_qube_led_driver);
-}
-
-module_init(cobalt_qube_led_init);
-module_exit(cobalt_qube_led_exit);
+module_platform_driver(cobalt_qube_led_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Front LED support for Cobalt Server");
 MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_ALIAS("platform:cobalt-qube-leds");
index f28931c..d9cd73e 100644 (file)
@@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = {
        .remove         = __devexit_p(da903x_led_remove),
 };
 
-static int __init da903x_led_init(void)
-{
-       return platform_driver_register(&da903x_led_driver);
-}
-module_init(da903x_led_init);
-
-static void __exit da903x_led_exit(void)
-{
-       platform_driver_unregister(&da903x_led_driver);
-}
-module_exit(da903x_led_exit);
+module_platform_driver(da903x_led_driver);
 
 MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
 MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
index 31cf0d6..d56c142 100644 (file)
@@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = {
        },
 };
 
-static int __init dac124s085_leds_init(void)
-{
-       return spi_register_driver(&dac124s085_driver);
-}
-
-static void __exit dac124s085_leds_exit(void)
-{
-       spi_unregister_driver(&dac124s085_driver);
-}
-
-module_init(dac124s085_leds_init);
-module_exit(dac124s085_leds_exit);
+module_spi_driver(dac124s085_driver);
 
 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
 MODULE_DESCRIPTION("DAC124S085 LED driver");
index 49aceff..b9053fa 100644 (file)
@@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = {
        },
 };
 
-
-static int __init fsg_led_init(void)
-{
-       return platform_driver_register(&fsg_led_driver);
-}
-
-static void __exit fsg_led_exit(void)
-{
-       platform_driver_unregister(&fsg_led_driver);
-}
-
-
-module_init(fsg_led_init);
-module_exit(fsg_led_exit);
+module_platform_driver(fsg_led_driver);
 
 MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
 MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
index 399a86f..7df74cb 100644 (file)
@@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = {
        },
 };
 
-MODULE_ALIAS("platform:leds-gpio");
-
-static int __init gpio_led_init(void)
-{
-       return platform_driver_register(&gpio_led_driver);
-}
-
-static void __exit gpio_led_exit(void)
-{
-       platform_driver_unregister(&gpio_led_driver);
-}
-
-module_init(gpio_led_init);
-module_exit(gpio_led_exit);
+module_platform_driver(gpio_led_driver);
 
 MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
 MODULE_DESCRIPTION("GPIO LED driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-gpio");
index bcfbd3a..366b605 100644 (file)
@@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev)
        return 0;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:hp6xx-led");
-
 static struct platform_driver hp6xxled_driver = {
        .probe          = hp6xxled_probe,
        .remove         = hp6xxled_remove,
@@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = {
        },
 };
 
-static int __init hp6xxled_init(void)
-{
-       return platform_driver_register(&hp6xxled_driver);
-}
-
-static void __exit hp6xxled_exit(void)
-{
-       platform_driver_unregister(&hp6xxled_driver);
-}
-
-module_init(hp6xxled_init);
-module_exit(hp6xxled_exit);
+module_platform_driver(hp6xxled_driver);
 
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hp6xx-led");
index 0630e4f..45e6878 100644 (file)
@@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = {
        },
 };
 
-static int __init lm3530_init(void)
-{
-       return i2c_add_driver(&lm3530_i2c_driver);
-}
-
-static void __exit lm3530_exit(void)
-{
-       i2c_del_driver(&lm3530_i2c_driver);
-}
-
-module_init(lm3530_init);
-module_exit(lm3530_exit);
+module_i2c_driver(lm3530_i2c_driver);
 
 MODULE_DESCRIPTION("Back Light driver for LM3530");
 MODULE_LICENSE("GPL v2");
index 9010c05..b8f9f0a 100644 (file)
@@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = {
        .id_table = lp3944_id,
 };
 
-static int __init lp3944_module_init(void)
-{
-       return i2c_add_driver(&lp3944_driver);
-}
-
-static void __exit lp3944_module_exit(void)
-{
-       i2c_del_driver(&lp3944_driver);
-}
-
-module_init(lp3944_module_init);
-module_exit(lp3944_module_exit);
+module_i2c_driver(lp3944_driver);
 
 MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 MODULE_DESCRIPTION("LP3944 Fun Light Chip");
index cb641f1..d62a798 100644 (file)
@@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = {
        .id_table       = lp5521_id,
 };
 
-static int __init lp5521_init(void)
-{
-       int ret;
-
-       ret = i2c_add_driver(&lp5521_driver);
-
-       if (ret < 0)
-               printk(KERN_ALERT "Adding lp5521 driver failed\n");
-
-       return ret;
-}
-
-static void __exit lp5521_exit(void)
-{
-       i2c_del_driver(&lp5521_driver);
-}
-
-module_init(lp5521_init);
-module_exit(lp5521_exit);
+module_i2c_driver(lp5521_driver);
 
 MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
 MODULE_DESCRIPTION("LP5521 LED engine");
index 5971e30..73e791a 100644 (file)
@@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
        return 0;
 }
 
-static struct i2c_driver lp5523_driver;
-
 static int __devinit lp5523_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = {
        .id_table       = lp5523_id,
 };
 
-static int __init lp5523_init(void)
-{
-       int ret;
-
-       ret = i2c_add_driver(&lp5523_driver);
-
-       if (ret < 0)
-               printk(KERN_ALERT "Adding lp5523 driver failed\n");
-
-       return ret;
-}
-
-static void __exit lp5523_exit(void)
-{
-       i2c_del_driver(&lp5523_driver);
-}
-
-module_init(lp5523_init);
-module_exit(lp5523_exit);
+module_i2c_driver(lp5523_driver);
 
 MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
 MODULE_DESCRIPTION("LP5523 LED engine");
index 53f67b8..e311a96 100644 (file)
@@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = {
        },
 };
 
-MODULE_ALIAS("platform:leds-lt3593");
-
-static int __init lt3593_led_init(void)
-{
-       return platform_driver_register(&lt3593_led_driver);
-}
-
-static void __exit lt3593_led_exit(void)
-{
-       platform_driver_unregister(&lt3593_led_driver);
-}
-
-module_init(lt3593_led_init);
-module_exit(lt3593_led_exit);
+module_platform_driver(lt3593_led_driver);
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 MODULE_DESCRIPTION("LED driver for LT3593 controllers");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-lt3593");
index b3393a9..8bc4915 100644 (file)
@@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) {
+       if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) {
                dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
                return -EINVAL;
        }
@@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = {
        .remove         = __devexit_p(mc13783_led_remove),
 };
 
-static int __init mc13783_led_init(void)
-{
-       return platform_driver_register(&mc13783_led_driver);
-}
-module_init(mc13783_led_init);
-
-static void __exit mc13783_led_exit(void)
-{
-       platform_driver_unregister(&mc13783_led_driver);
-}
-module_exit(mc13783_led_exit);
+module_platform_driver(mc13783_led_driver);
 
 MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
 MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
index f2e51c1..d8433f2 100644 (file)
@@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
 
        /* Configure address GPIOs. */
        for (i = 0; i < gpio_ext->num_addr; i++) {
-               err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
+               err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW,
+                                      "GPIO extension addr");
                if (err)
                        goto err_free_addr;
-               err = gpio_direction_output(gpio_ext->addr[i], 0);
-               if (err) {
-                       gpio_free(gpio_ext->addr[i]);
-                       goto err_free_addr;
-               }
        }
        /* Configure data GPIOs. */
        for (i = 0; i < gpio_ext->num_data; i++) {
-               err = gpio_request(gpio_ext->data[i], "GPIO extension data");
+               err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW,
+                                  "GPIO extension data");
                if (err)
                        goto err_free_data;
-               err = gpio_direction_output(gpio_ext->data[i], 0);
-               if (err) {
-                       gpio_free(gpio_ext->data[i]);
-                       goto err_free_data;
-               }
        }
        /* Configure "enable select" GPIO. */
-       err = gpio_request(gpio_ext->enable, "GPIO extension enable");
+       err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW,
+                              "GPIO extension enable");
        if (err)
                goto err_free_data;
-       err = gpio_direction_output(gpio_ext->enable, 0);
-       if (err) {
-               gpio_free(gpio_ext->enable);
-               goto err_free_data;
-       }
 
        return 0;
 
@@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = {
                .owner  = THIS_MODULE,
        },
 };
-MODULE_ALIAS("platform:leds-netxbig");
 
-static int __init netxbig_led_init(void)
-{
-       return platform_driver_register(&netxbig_led_driver);
-}
-
-static void __exit netxbig_led_exit(void)
-{
-       platform_driver_unregister(&netxbig_led_driver);
-}
-
-module_init(netxbig_led_init);
-module_exit(netxbig_led_exit);
+module_platform_driver(netxbig_led_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-netxbig");
index 37b7d0c..2f0a144 100644 (file)
@@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = {
                .owner  = THIS_MODULE,
        },
 };
-MODULE_ALIAS("platform:leds-ns2");
-
-static int __init ns2_led_init(void)
-{
-       return platform_driver_register(&ns2_led_driver);
-}
 
-static void __exit ns2_led_exit(void)
-{
-       platform_driver_unregister(&ns2_led_driver);
-}
-
-module_init(ns2_led_init);
-module_exit(ns2_led_exit);
+module_platform_driver(ns2_led_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("Network Space v2 LED driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ns2");
index a2c8746..ceccab4 100644 (file)
@@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client)
        return 0;
 }
 
-static int __init pca9532_init(void)
-{
-       return i2c_add_driver(&pca9532_driver);
-}
-
-static void __exit pca9532_exit(void)
-{
-       i2c_del_driver(&pca9532_driver);
-}
+module_i2c_driver(pca9532_driver);
 
 MODULE_AUTHOR("Riku Voipio");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PCA 9532 LED dimmer");
-
-module_init(pca9532_init);
-module_exit(pca9532_exit);
-
index 66aa3e8..dcc3bc3 100644 (file)
@@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = {
        .id_table = pca955x_id,
 };
 
-static int __init pca955x_leds_init(void)
-{
-       return i2c_add_driver(&pca955x_driver);
-}
-
-static void __exit pca955x_leds_exit(void)
-{
-       i2c_del_driver(&pca955x_driver);
-}
-
-module_init(pca955x_leds_init);
-module_exit(pca955x_leds_exit);
+module_i2c_driver(pca955x_driver);
 
 MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
 MODULE_DESCRIPTION("PCA955x LED driver");
index 666daf7..3ed92f3 100644 (file)
@@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = {
        },
 };
 
-static int __init led_pwm_init(void)
-{
-       return platform_driver_register(&led_pwm_driver);
-}
-
-static void __exit led_pwm_exit(void)
-{
-       platform_driver_unregister(&led_pwm_driver);
-}
-
-module_init(led_pwm_init);
-module_exit(led_pwm_exit);
+module_platform_driver(led_pwm_driver);
 
 MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
 MODULE_DESCRIPTION("PWM LED driver for PXA");
index c3525f3..a7815b6 100644 (file)
@@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = {
        },
 };
 
-static int __init rb532_led_init(void)
-{
-       return platform_driver_register(&rb532_led_driver);
-}
-
-static void __exit rb532_led_exit(void)
-{
-       platform_driver_unregister(&rb532_led_driver);
-}
-
-module_init(rb532_led_init);
-module_exit(rb532_led_exit);
-
-MODULE_ALIAS("platform:rb532-led");
+module_platform_driver(rb532_led_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("User LED support for Routerboard532");
 MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
+MODULE_ALIAS("platform:rb532-led");
index 8497f56..df7e963 100644 (file)
@@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = {
        .remove = __devexit_p(regulator_led_remove),
 };
 
-static int __init regulator_led_init(void)
-{
-       return platform_driver_register(&regulator_led_driver);
-}
-module_init(regulator_led_init);
-
-static void __exit regulator_led_exit(void)
-{
-       platform_driver_unregister(&regulator_led_driver);
-}
-module_exit(regulator_led_exit);
+module_platform_driver(regulator_led_driver);
 
 MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 MODULE_DESCRIPTION("Regulator driven LED driver");
index 3ee540e..32fe337 100644 (file)
@@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = {
        }
 };
 
-static int __init r_tpu_init(void)
-{
-       return platform_driver_register(&r_tpu_device_driver);
-}
-
-static void __exit r_tpu_exit(void)
-{
-       platform_driver_unregister(&r_tpu_device_driver);
-}
-
-module_init(r_tpu_init);
-module_exit(r_tpu_exit);
+module_platform_driver(r_tpu_device_driver);
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("Renesas TPU LED Driver");
index 29f8b0f..bd0a5ed 100644 (file)
@@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = {
        },
 };
 
-static int __init s3c24xx_led_init(void)
-{
-       return platform_driver_register(&s3c24xx_led_driver);
-}
-
-static void __exit s3c24xx_led_exit(void)
-{
-       platform_driver_unregister(&s3c24xx_led_driver);
-}
-
-module_init(s3c24xx_led_init);
-module_exit(s3c24xx_led_exit);
+module_platform_driver(s3c24xx_led_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C24XX LED driver");
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
new file mode 100644 (file)
index 0000000..133f89f
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * leds-tca6507
+ *
+ * The TCA6507 is a programmable LED controller that can drive 7
+ * separate lines either by holding them low, or by pulsing them
+ * with modulated width.
+ * The modulation can be varied in a simple pattern to produce a blink or
+ * double-blink.
+ *
+ * This driver can configure each line either as a 'GPIO' which is out-only
+ * (no pull-up) or as an LED with variable brightness and hardware-assisted
+ * blinking.
+ *
+ * Apart from OFF and ON there are three programmable brightness levels which
+ * can be programmed from 0 to 15 and indicate how many 500usec intervals in
+ * each 8msec that the led is 'on'.  The levels are named MASTER, BANK0 and
+ * BANK1.
+ *
+ * There are two different blink rates that can be programmed, each with
+ * separate time for rise, on, fall, off and second-off.  Thus if 3 or more
+ * different non-trivial rates are required, software must be used for the extra
+ * rates. The two different blink rates must align with the two levels BANK0 and
+ * BANK1.
+ * This driver does not support double-blink so 'second-off' always matches
+ * 'off'.
+ *
+ * Only 16 different times can be programmed in a roughly logarithmic scale from
+ * 64ms to 16320ms.  To be precise the possible times are:
+ *    0, 64, 128, 192, 256, 384, 512, 768,
+ *    1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
+ *
+ * Times that cannot be closely matched with these must be
+ * handled in software.  This driver allows 12.5% error in matching.
+ *
+ * This driver does not allow rise/fall rates to be set explicitly.  When trying
+ * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
+ * 'hold' times are chosen to get a close match.  If the target delay is even,
+ * the 'change' number will be the smaller; if odd, the 'hold' number will be
+ * the smaller.
+
+ * Choosing pairs of delays with 12.5% errors allows us to match delays in the
+ * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
+ * 26% of the achievable sums can be matched by multiple pairings. For example
+ * 1536 == 1536+0, 1024+512, or 768+768.  This driver will always choose the
+ * pairing with the least maximum - 768+768 in this case.  Other pairings are
+ * not available.
+ *
+ * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
+ * Access can be shared by multiple leds if they have the same level and
+ * either same blink rates, or some don't blink.
+ * When a led changes, it relinquishes access and tries again, so it might
+ * lose access to hardware blink.
+ * If a blink engine cannot be allocated, software blink is used.
+ * If the desired brightness cannot be allocated, the closest available non-zero
+ * brightness is used.  As 'full' is always available, the worst case would be
+ * to have two different blink rates at '1', with Max at '2', then other leds
+ * will have to choose between '2' and '16'.  Hopefully this is not likely.
+ *
+ * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
+ * and LEDs using the blink.  It can only be reprogrammed when the appropriate
+ * counter is zero.  The MASTER level has a single usage count.
+ *
+ * Each Led has programmable 'on' and 'off' time as milliseconds.  With each
+ * there is a flag saying if it was explicitly requested or defaulted.
+ * Similarly the banks know if each time was explicit or a default.  Defaults
+ * are permitted to be changed freely - they are not recognised when matching.
+ *
+ *
+ * An led-tca6507 device must be provided with platform data.  This data
+ * lists for each output: the name, default trigger, and whether the signal
+ * is being used as a GPiO rather than an led.  'struct led_plaform_data'
+ * is used for this.  If 'name' is NULL, the output isn't used.  If 'flags'
+ * is TCA6507_MAKE_CPIO, the output is a GPO.
+ * The "struct led_platform_data" can be embedded in a
+ * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
+ * and a 'setup' callback which is called once the GPiOs are available.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/leds-tca6507.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define TCA6507_LS_LED_OFF     0x0     /* Output HI-Z (off) */
+#define TCA6507_LS_LED_OFF1    0x1     /* Output HI-Z (off) - not used */
+#define TCA6507_LS_LED_PWM0    0x2     /* Output LOW with Bank0 rate */
+#define TCA6507_LS_LED_PWM1    0x3     /* Output LOW with Bank1 rate */
+#define TCA6507_LS_LED_ON      0x4     /* Output LOW (on) */
+#define TCA6507_LS_LED_MIR     0x5     /* Output LOW with Master Intensity */
+#define TCA6507_LS_BLINK0      0x6     /* Blink at Bank0 rate */
+#define TCA6507_LS_BLINK1      0x7     /* Blink at Bank1 rate */
+
+enum {
+       BANK0,
+       BANK1,
+       MASTER,
+};
+static int bank_source[3] = {
+       TCA6507_LS_LED_PWM0,
+       TCA6507_LS_LED_PWM1,
+       TCA6507_LS_LED_MIR,
+};
+static int blink_source[2] = {
+       TCA6507_LS_BLINK0,
+       TCA6507_LS_BLINK1,
+};
+
+/* PWM registers */
+#define        TCA6507_REG_CNT                 11
+
+/*
+ * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output
+ * owns one bit in each register
+ */
+#define        TCA6507_FADE_ON                 0x03
+#define        TCA6507_FULL_ON                 0x04
+#define        TCA6507_FADE_OFF                0x05
+#define        TCA6507_FIRST_OFF               0x06
+#define        TCA6507_SECOND_OFF              0x07
+#define        TCA6507_MAX_INTENSITY           0x08
+#define        TCA6507_MASTER_INTENSITY        0x09
+#define        TCA6507_INITIALIZE              0x0A
+
+#define        INIT_CODE                       0x8
+
+#define TIMECODES 16
+static int time_codes[TIMECODES] = {
+       0, 64, 128, 192, 256, 384, 512, 768,
+       1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
+};
+
+/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */
+static inline int TO_LEVEL(int brightness)
+{
+       return brightness >> 4;
+}
+
+/* ...and convert back */
+static inline int TO_BRIGHT(int level)
+{
+       if (level)
+               return (level << 4) | 0xf;
+       return 0;
+}
+
+#define NUM_LEDS 7
+struct tca6507_chip {
+       int                     reg_set;        /* One bit per register where
+                                                * a '1' means the register
+                                                * should be written */
+       u8                      reg_file[TCA6507_REG_CNT];
+       /* Bank 2 is Master Intensity and doesn't use times */
+       struct bank {
+               int level;
+               int ontime, offtime;
+               int on_dflt, off_dflt;
+               int time_use, level_use;
+       } bank[3];
+       struct i2c_client       *client;
+       struct work_struct      work;
+       spinlock_t              lock;
+
+       struct tca6507_led {
+               struct tca6507_chip     *chip;
+               struct led_classdev     led_cdev;
+               int                     num;
+               int                     ontime, offtime;
+               int                     on_dflt, off_dflt;
+               int                     bank;   /* Bank used, or -1 */
+               int                     blink;  /* Set if hardware-blinking */
+       } leds[NUM_LEDS];
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip                gpio;
+       const char                      *gpio_name[NUM_LEDS];
+       int                             gpio_map[NUM_LEDS];
+#endif
+};
+
+static const struct i2c_device_id tca6507_id[] = {
+       { "tca6507" },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tca6507_id);
+
+static int choose_times(int msec, int *c1p, int *c2p)
+{
+       /*
+        * Choose two timecodes which add to 'msec' as near as possible.
+        * The first returned is the 'on' or 'off' time.  The second is to be
+        * used as a 'fade-on' or 'fade-off' time.  If 'msec' is even,
+        * the first will not be smaller than the second.  If 'msec' is odd,
+        * the first will not be larger than the second.
+        * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
+        * otherwise return the sum that was achieved, plus 1 if the first is
+        * smaller.
+        * If two possibilities are equally good (e.g. 512+0, 256+256), choose
+        * the first pair so there is more change-time visible (i.e. it is
+        * softer).
+        */
+       int c1, c2;
+       int tmax = msec * 9 / 8;
+       int tmin = msec * 7 / 8;
+       int diff = 65536;
+
+       /* We start at '1' to ensure we never even think of choosing a
+        * total time of '0'.
+        */
+       for (c1 = 1; c1 < TIMECODES; c1++) {
+               int t = time_codes[c1];
+               if (t*2 < tmin)
+                       continue;
+               if (t > tmax)
+                       break;
+               for (c2 = 0; c2 <= c1; c2++) {
+                       int tt = t + time_codes[c2];
+                       int d;
+                       if (tt < tmin)
+                               continue;
+                       if (tt > tmax)
+                               break;
+                       /* This works! */
+                       d = abs(msec - tt);
+                       if (d >= diff)
+                               continue;
+                       /* Best yet */
+                       *c1p = c1;
+                       *c2p = c2;
+                       diff = d;
+                       if (d == 0)
+                               return msec;
+               }
+       }
+       if (diff < 65536) {
+               int actual;
+               if (msec & 1) {
+                       c1 = *c2p;
+                       *c2p = *c1p;
+                       *c1p = c1;
+               }
+               actual = time_codes[*c1p] + time_codes[*c2p];
+               if (*c1p < *c2p)
+                       return actual + 1;
+               else
+                       return actual;
+       }
+       /* No close match */
+       return -EINVAL;
+}
+
+/*
+ * Update the register file with the appropriate 3-bit state for
+ * the given led.
+ */
+static void set_select(struct tca6507_chip *tca, int led, int val)
+{
+       int mask = (1 << led);
+       int bit;
+
+       for (bit = 0; bit < 3; bit++) {
+               int n = tca->reg_file[bit] & ~mask;
+               if (val & (1 << bit))
+                       n |= mask;
+               if (tca->reg_file[bit] != n) {
+                       tca->reg_file[bit] = n;
+                       tca->reg_set |= (1 << bit);
+               }
+       }
+}
+
+/* Update the register file with the appropriate 4-bit code for
+ * one bank or other.  This can be used for timers, for levels, or
+ * for initialisation.
+ */
+static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
+{
+       int mask = 0xF;
+       int n;
+       if (bank) {
+               mask <<= 4;
+               new <<= 4;
+       }
+       n = tca->reg_file[reg] & ~mask;
+       n |= new;
+       if (tca->reg_file[reg] != n) {
+               tca->reg_file[reg] = n;
+               tca->reg_set |= 1 << reg;
+       }
+}
+
+/* Update brightness level. */
+static void set_level(struct tca6507_chip *tca, int bank, int level)
+{
+       switch (bank) {
+       case BANK0:
+       case BANK1:
+               set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
+               break;
+       case MASTER:
+               set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
+               break;
+       }
+       tca->bank[bank].level = level;
+}
+
+/* Record all relevant time code for a given bank */
+static void set_times(struct tca6507_chip *tca, int bank)
+{
+       int c1, c2;
+       int result;
+
+       result = choose_times(tca->bank[bank].ontime, &c1, &c2);
+       dev_dbg(&tca->client->dev,
+               "Chose on  times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               c2, time_codes[c2], tca->bank[bank].ontime);
+       set_code(tca, TCA6507_FADE_ON, bank, c2);
+       set_code(tca, TCA6507_FULL_ON, bank, c1);
+       tca->bank[bank].ontime = result;
+
+       result = choose_times(tca->bank[bank].offtime, &c1, &c2);
+       dev_dbg(&tca->client->dev,
+               "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               c2, time_codes[c2], tca->bank[bank].offtime);
+       set_code(tca, TCA6507_FADE_OFF, bank, c2);
+       set_code(tca, TCA6507_FIRST_OFF, bank, c1);
+       set_code(tca, TCA6507_SECOND_OFF, bank, c1);
+       tca->bank[bank].offtime = result;
+
+       set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
+}
+
+/* Write all needed register of tca6507 */
+
+static void tca6507_work(struct work_struct *work)
+{
+       struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
+                                               work);
+       struct i2c_client *cl = tca->client;
+       int set;
+       u8 file[TCA6507_REG_CNT];
+       int r;
+
+       spin_lock_irq(&tca->lock);
+       set = tca->reg_set;
+       memcpy(file, tca->reg_file, TCA6507_REG_CNT);
+       tca->reg_set = 0;
+       spin_unlock_irq(&tca->lock);
+
+       for (r = 0; r < TCA6507_REG_CNT; r++)
+               if (set & (1<<r))
+                       i2c_smbus_write_byte_data(cl, r, file[r]);
+}
+
+static void led_release(struct tca6507_led *led)
+{
+       /* If led owns any resource, release it. */
+       struct tca6507_chip *tca = led->chip;
+       if (led->bank >= 0) {
+               struct bank *b = tca->bank + led->bank;
+               if (led->blink)
+                       b->time_use--;
+               b->level_use--;
+       }
+       led->blink = 0;
+       led->bank = -1;
+}
+
+static int led_prepare(struct tca6507_led *led)
+{
+       /* Assign this led to a bank, configuring that bank if necessary. */
+       int level = TO_LEVEL(led->led_cdev.brightness);
+       struct tca6507_chip *tca = led->chip;
+       int c1, c2;
+       int i;
+       struct bank *b;
+       int need_init = 0;
+
+       led->led_cdev.brightness = TO_BRIGHT(level);
+       if (level == 0) {
+               set_select(tca, led->num, TCA6507_LS_LED_OFF);
+               return 0;
+       }
+
+       if (led->ontime == 0 || led->offtime == 0) {
+               /*
+                * Just set the brightness, choosing first usable bank.
+                * If none perfect, choose best.
+                * Count backwards so we check MASTER bank first
+                * to avoid wasting a timer.
+                */
+               int best = -1;/* full-on */
+               int diff = 15-level;
+
+               if (level == 15) {
+                       set_select(tca, led->num, TCA6507_LS_LED_ON);
+                       return 0;
+               }
+
+               for (i = MASTER; i >= BANK0; i--) {
+                       int d;
+                       if (tca->bank[i].level == level ||
+                           tca->bank[i].level_use == 0) {
+                               best = i;
+                               break;
+                       }
+                       d = abs(level - tca->bank[i].level);
+                       if (d < diff) {
+                               diff = d;
+                               best = i;
+                       }
+               }
+               if (best == -1) {
+                       /* Best brightness is full-on */
+                       set_select(tca, led->num, TCA6507_LS_LED_ON);
+                       led->led_cdev.brightness = LED_FULL;
+                       return 0;
+               }
+
+               if (!tca->bank[best].level_use)
+                       set_level(tca, best, level);
+
+               tca->bank[best].level_use++;
+               led->bank = best;
+               set_select(tca, led->num, bank_source[best]);
+               led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
+               return 0;
+       }
+
+       /*
+        * We have on/off time so we need to try to allocate a timing bank.
+        * First check if times are compatible with hardware and give up if
+        * not.
+        */
+       if (choose_times(led->ontime, &c1, &c2) < 0)
+               return -EINVAL;
+       if (choose_times(led->offtime, &c1, &c2) < 0)
+               return -EINVAL;
+
+       for (i = BANK0; i <= BANK1; i++) {
+               if (tca->bank[i].level_use == 0)
+                       /* not in use - it is ours! */
+                       break;
+               if (tca->bank[i].level != level)
+                       /* Incompatible level - skip */
+                       /* FIX: if timer matches we maybe should consider
+                        * this anyway...
+                        */
+                       continue;
+
+               if (tca->bank[i].time_use == 0)
+                       /* Timer not in use, and level matches - use it */
+                       break;
+
+               if (!(tca->bank[i].on_dflt ||
+                     led->on_dflt ||
+                     tca->bank[i].ontime == led->ontime))
+                       /* on time is incompatible */
+                       continue;
+
+               if (!(tca->bank[i].off_dflt ||
+                     led->off_dflt ||
+                     tca->bank[i].offtime == led->offtime))
+                       /* off time is incompatible */
+                       continue;
+
+               /* looks like a suitable match */
+               break;
+       }
+
+       if (i > BANK1)
+               /* Nothing matches - how sad */
+               return -EINVAL;
+
+       b = &tca->bank[i];
+       if (b->level_use == 0)
+               set_level(tca, i, level);
+       b->level_use++;
+       led->bank = i;
+
+       if (b->on_dflt ||
+           !led->on_dflt ||
+           b->time_use == 0) {
+               b->ontime = led->ontime;
+               b->on_dflt = led->on_dflt;
+               need_init = 1;
+       }
+
+       if (b->off_dflt ||
+           !led->off_dflt ||
+           b->time_use == 0) {
+               b->offtime = led->offtime;
+               b->off_dflt = led->off_dflt;
+               need_init = 1;
+       }
+
+       if (need_init)
+               set_times(tca, i);
+
+       led->ontime = b->ontime;
+       led->offtime = b->offtime;
+
+       b->time_use++;
+       led->blink = 1;
+       led->led_cdev.brightness = TO_BRIGHT(b->level);
+       set_select(tca, led->num, blink_source[i]);
+       return 0;
+}
+
+static int led_assign(struct tca6507_led *led)
+{
+       struct tca6507_chip *tca = led->chip;
+       int err;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tca->lock, flags);
+       led_release(led);
+       err = led_prepare(led);
+       if (err) {
+               /*
+                * Can only fail on timer setup.  In that case we need to
+                * re-establish as steady level.
+                */
+               led->ontime = 0;
+               led->offtime = 0;
+               led_prepare(led);
+       }
+       spin_unlock_irqrestore(&tca->lock, flags);
+
+       if (tca->reg_set)
+               schedule_work(&tca->work);
+       return err;
+}
+
+static void tca6507_brightness_set(struct led_classdev *led_cdev,
+                                  enum led_brightness brightness)
+{
+       struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
+                                              led_cdev);
+       led->led_cdev.brightness = brightness;
+       led->ontime = 0;
+       led->offtime = 0;
+       led_assign(led);
+}
+
+static int tca6507_blink_set(struct led_classdev *led_cdev,
+                            unsigned long *delay_on,
+                            unsigned long *delay_off)
+{
+       struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
+                                              led_cdev);
+
+       if (*delay_on == 0)
+               led->on_dflt = 1;
+       else if (delay_on != &led_cdev->blink_delay_on)
+               led->on_dflt = 0;
+       led->ontime = *delay_on;
+
+       if (*delay_off == 0)
+               led->off_dflt = 1;
+       else if (delay_off != &led_cdev->blink_delay_off)
+               led->off_dflt = 0;
+       led->offtime = *delay_off;
+
+       if (led->ontime == 0)
+               led->ontime = 512;
+       if (led->offtime == 0)
+               led->offtime = 512;
+
+       if (led->led_cdev.brightness == LED_OFF)
+               led->led_cdev.brightness = LED_FULL;
+       if (led_assign(led) < 0) {
+               led->ontime = 0;
+               led->offtime = 0;
+               led->led_cdev.brightness = LED_OFF;
+               return -EINVAL;
+       }
+       *delay_on = led->ontime;
+       *delay_off = led->offtime;
+       return 0;
+}
+
+#ifdef CONFIG_GPIOLIB
+static void tca6507_gpio_set_value(struct gpio_chip *gc,
+                                  unsigned offset, int val)
+{
+       struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tca->lock, flags);
+       /*
+        * 'OFF' is floating high, and 'ON' is pulled down, so it has the
+        * inverse sense of 'val'.
+        */
+       set_select(tca, tca->gpio_map[offset],
+                  val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
+       spin_unlock_irqrestore(&tca->lock, flags);
+       if (tca->reg_set)
+               schedule_work(&tca->work);
+}
+
+static int tca6507_gpio_direction_output(struct gpio_chip *gc,
+                                         unsigned offset, int val)
+{
+       tca6507_gpio_set_value(gc, offset, val);
+       return 0;
+}
+
+static int tca6507_probe_gpios(struct i2c_client *client,
+                              struct tca6507_chip *tca,
+                              struct tca6507_platform_data *pdata)
+{
+       int err;
+       int i = 0;
+       int gpios = 0;
+
+       for (i = 0; i < NUM_LEDS; i++)
+               if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
+                       /* Configure as a gpio */
+                       tca->gpio_name[gpios] = pdata->leds.leds[i].name;
+                       tca->gpio_map[gpios] = i;
+                       gpios++;
+               }
+
+       if (!gpios)
+               return 0;
+
+       tca->gpio.label = "gpio-tca6507";
+       tca->gpio.names = tca->gpio_name;
+       tca->gpio.ngpio = gpios;
+       tca->gpio.base = pdata->gpio_base;
+       tca->gpio.owner = THIS_MODULE;
+       tca->gpio.direction_output = tca6507_gpio_direction_output;
+       tca->gpio.set = tca6507_gpio_set_value;
+       tca->gpio.dev = &client->dev;
+       err = gpiochip_add(&tca->gpio);
+       if (err) {
+               tca->gpio.ngpio = 0;
+               return err;
+       }
+       if (pdata->setup)
+               pdata->setup(tca->gpio.base, tca->gpio.ngpio);
+       return 0;
+}
+
+static void tca6507_remove_gpio(struct tca6507_chip *tca)
+{
+       if (tca->gpio.ngpio) {
+               int err = gpiochip_remove(&tca->gpio);
+               dev_err(&tca->client->dev, "%s failed, %d\n",
+                       "gpiochip_remove()", err);
+       }
+}
+#else /* CONFIG_GPIOLIB */
+static int tca6507_probe_gpios(struct i2c_client *client,
+                              struct tca6507_chip *tca,
+                              struct tca6507_platform_data *pdata)
+{
+       return 0;
+}
+static void tca6507_remove_gpio(struct tca6507_chip *tca)
+{
+}
+#endif /* CONFIG_GPIOLIB */
+
+static int __devinit tca6507_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct tca6507_chip *tca;
+       struct i2c_adapter *adapter;
+       struct tca6507_platform_data *pdata;
+       int err;
+       int i = 0;
+
+       adapter = to_i2c_adapter(client->dev.parent);
+       pdata = client->dev.platform_data;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+               return -EIO;
+
+       if (!pdata || pdata->leds.num_leds != NUM_LEDS) {
+               dev_err(&client->dev, "Need %d entries in platform-data list\n",
+                       NUM_LEDS);
+               return -ENODEV;
+       }
+       err = -ENOMEM;
+       tca = kzalloc(sizeof(*tca), GFP_KERNEL);
+       if (!tca)
+               goto exit;
+
+       tca->client = client;
+       INIT_WORK(&tca->work, tca6507_work);
+       spin_lock_init(&tca->lock);
+       i2c_set_clientdata(client, tca);
+
+       for (i = 0; i < NUM_LEDS; i++) {
+               struct tca6507_led *l = tca->leds + i;
+
+               l->chip = tca;
+               l->num = i;
+               if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
+                       l->led_cdev.name = pdata->leds.leds[i].name;
+                       l->led_cdev.default_trigger
+                               = pdata->leds.leds[i].default_trigger;
+                       l->led_cdev.brightness_set = tca6507_brightness_set;
+                       l->led_cdev.blink_set = tca6507_blink_set;
+                       l->bank = -1;
+                       err = led_classdev_register(&client->dev,
+                                                   &l->led_cdev);
+                       if (err < 0)
+                               goto exit;
+               }
+       }
+       err = tca6507_probe_gpios(client, tca, pdata);
+       if (err)
+               goto exit;
+       /* set all registers to known state - zero */
+       tca->reg_set = 0x7f;
+       schedule_work(&tca->work);
+
+       return 0;
+exit:
+       while (i--)
+               if (tca->leds[i].led_cdev.name)
+                       led_classdev_unregister(&tca->leds[i].led_cdev);
+       cancel_work_sync(&tca->work);
+       i2c_set_clientdata(client, NULL);
+       kfree(tca);
+       return err;
+}
+
+static int __devexit tca6507_remove(struct i2c_client *client)
+{
+       int i;
+       struct tca6507_chip *tca = i2c_get_clientdata(client);
+       struct tca6507_led *tca_leds = tca->leds;
+
+       for (i = 0; i < NUM_LEDS; i++) {
+               if (tca_leds[i].led_cdev.name)
+                       led_classdev_unregister(&tca_leds[i].led_cdev);
+       }
+       tca6507_remove_gpio(tca);
+       cancel_work_sync(&tca->work);
+       i2c_set_clientdata(client, NULL);
+       kfree(tca);
+
+       return 0;
+}
+
+static struct i2c_driver tca6507_driver = {
+       .driver   = {
+               .name    = "leds-tca6507",
+               .owner   = THIS_MODULE,
+       },
+       .probe    = tca6507_probe,
+       .remove   = __devexit_p(tca6507_remove),
+       .id_table = tca6507_id,
+};
+
+static int __init tca6507_leds_init(void)
+{
+       return i2c_add_driver(&tca6507_driver);
+}
+
+static void __exit tca6507_leds_exit(void)
+{
+       i2c_del_driver(&tca6507_driver);
+}
+
+module_init(tca6507_leds_init);
+module_exit(tca6507_leds_exit);
+
+MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
+MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
+MODULE_LICENSE("GPL v2");
index b1eb34c..74a24cf 100644 (file)
@@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev)
                goto err;
        }
 
-       drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL);
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
+                              GFP_KERNEL);
        if (!drvdata)
                return -ENOMEM;
        dev_set_drvdata(&pdev->dev, drvdata);
@@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
 
 err_led:
        led_classdev_unregister(&drvdata->cdev);
-       kfree(drvdata);
 err:
        return ret;
 }
@@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev)
 
        device_remove_file(drvdata->cdev.dev, &dev_attr_src);
        led_classdev_unregister(&drvdata->cdev);
-       kfree(drvdata);
 
        return 0;
 }
@@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = {
        .remove = wm831x_status_remove,
 };
 
-static int __devinit wm831x_status_init(void)
-{
-       return platform_driver_register(&wm831x_status_driver);
-}
-module_init(wm831x_status_init);
-
-static void wm831x_status_exit(void)
-{
-       platform_driver_unregister(&wm831x_status_driver);
-}
-module_exit(wm831x_status_exit);
+module_platform_driver(wm831x_status_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM831x status LED driver");
index 4a12765..918d4ba 100644 (file)
@@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
                goto err_isink;
        }
 
-       led = kzalloc(sizeof(*led), GFP_KERNEL);
+       led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
        if (led == NULL) {
                ret = -ENOMEM;
                goto err_dcdc;
@@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev)
 
        ret = led_classdev_register(&pdev->dev, &led->cdev);
        if (ret < 0)
-               goto err_led;
+               goto err_dcdc;
 
        return 0;
 
- err_led:
-       kfree(led);
  err_dcdc:
        regulator_put(dcdc);
  err_isink:
@@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
        wm8350_led_disable(led);
        regulator_put(led->dcdc);
        regulator_put(led->isink);
-       kfree(led);
        return 0;
 }
 
@@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = {
        .shutdown = wm8350_led_shutdown,
 };
 
-static int __devinit wm8350_led_init(void)
-{
-       return platform_driver_register(&wm8350_led_driver);
-}
-module_init(wm8350_led_init);
-
-static void wm8350_led_exit(void)
-{
-       platform_driver_unregister(&wm8350_led_driver);
-}
-module_exit(wm8350_led_exit);
+module_platform_driver(wm8350_led_driver);
 
 MODULE_AUTHOR("Mark Brown");
 MODULE_DESCRIPTION("WM8350 LED driver");
index 8e28625..8a1c031 100644 (file)
@@ -228,11 +228,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
                alarm->time.tm_hour = now.tm_hour;
 
        /* For simplicity, only support date rollover for now */
-       if (alarm->time.tm_mday == -1) {
+       if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
                alarm->time.tm_mday = now.tm_mday;
                missing = day;
        }
-       if (alarm->time.tm_mon == -1) {
+       if ((unsigned)alarm->time.tm_mon >= 12) {
                alarm->time.tm_mon = now.tm_mon;
                if (missing == none)
                        missing = month;
index 64b847b..f04761e 100644 (file)
@@ -410,17 +410,7 @@ static struct platform_driver pm860x_rtc_driver = {
        .remove         = __devexit_p(pm860x_rtc_remove),
 };
 
-static int __init pm860x_rtc_init(void)
-{
-       return platform_driver_register(&pm860x_rtc_driver);
-}
-module_init(pm860x_rtc_init);
-
-static void __exit pm860x_rtc_exit(void)
-{
-       platform_driver_unregister(&pm860x_rtc_driver);
-}
-module_exit(pm860x_rtc_exit);
+module_platform_driver(pm860x_rtc_driver);
 
 MODULE_DESCRIPTION("Marvell 88PM860x RTC driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index e346705..a0a9810 100644 (file)
@@ -90,7 +90,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
        /* Early AB8500 chips will not clear the rtc read request bit */
        if (abx500_get_chip_id(dev) == 0) {
-               msleep(1);
+               usleep_range(1000, 1000);
        } else {
                /* Wait for some cycles after enabling the rtc read in ab8500 */
                while (time_before(jiffies, timeout)) {
@@ -102,7 +102,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
                        if (!(value & RTC_READ_REQUEST))
                                break;
 
-                       msleep(1);
+                       usleep_range(1000, 5000);
                }
        }
 
@@ -258,6 +258,109 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        return ab8500_rtc_irq_enable(dev, alarm->enabled);
 }
 
+
+static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
+{
+       int retval;
+       u8  rtccal = 0;
+
+       /*
+        * Check that the calibration value (which is in units of 0.5
+        * parts-per-million) is in the AB8500's range for RtcCalibration
+        * register. -128 (0x80) is not permitted because the AB8500 uses
+        * a sign-bit rather than two's complement, so 0x80 is just another
+        * representation of zero.
+        */
+       if ((calibration < -127) || (calibration > 127)) {
+               dev_err(dev, "RtcCalibration value outside permitted range\n");
+               return -EINVAL;
+       }
+
+       /*
+        * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
+        * so need to convert to this sort of representation before writing
+        * into RtcCalibration register...
+        */
+       if (calibration >= 0)
+               rtccal = 0x7F & calibration;
+       else
+               rtccal = ~(calibration - 1) | 0x80;
+
+       retval = abx500_set_register_interruptible(dev, AB8500_RTC,
+                       AB8500_RTC_CALIB_REG, rtccal);
+
+       return retval;
+}
+
+static int ab8500_rtc_get_calibration(struct device *dev, int *calibration)
+{
+       int retval;
+       u8  rtccal = 0;
+
+       retval =  abx500_get_register_interruptible(dev, AB8500_RTC,
+                       AB8500_RTC_CALIB_REG, &rtccal);
+       if (retval >= 0) {
+               /*
+                * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
+                * so need to convert value from RtcCalibration register into
+                * a two's complement signed value...
+                */
+               if (rtccal & 0x80)
+                       *calibration = 0 - (rtccal & 0x7F);
+               else
+                       *calibration = 0x7F & rtccal;
+       }
+
+       return retval;
+}
+
+static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int retval;
+       int calibration = 0;
+
+       if (sscanf(buf, " %i ", &calibration) != 1) {
+               dev_err(dev, "Failed to store RTC calibration attribute\n");
+               return -EINVAL;
+       }
+
+       retval = ab8500_rtc_set_calibration(dev, calibration);
+
+       return retval ? retval : count;
+}
+
+static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int  retval = 0;
+       int  calibration = 0;
+
+       retval = ab8500_rtc_get_calibration(dev, &calibration);
+       if (retval < 0) {
+               dev_err(dev, "Failed to read RTC calibration attribute\n");
+               sprintf(buf, "0\n");
+               return retval;
+       }
+
+       return sprintf(buf, "%d\n", calibration);
+}
+
+static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
+                  ab8500_sysfs_show_rtc_calibration,
+                  ab8500_sysfs_store_rtc_calibration);
+
+static int ab8500_sysfs_rtc_register(struct device *dev)
+{
+       return device_create_file(dev, &dev_attr_rtc_calibration);
+}
+
+static void ab8500_sysfs_rtc_unregister(struct device *dev)
+{
+       device_remove_file(dev, &dev_attr_rtc_calibration);
+}
+
 static irqreturn_t rtc_alarm_handler(int irq, void *data)
 {
        struct rtc_device *rtc = data;
@@ -295,7 +398,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
                return err;
 
        /* Wait for reset by the PorRtc */
-       msleep(1);
+       usleep_range(1000, 5000);
 
        err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC,
                AB8500_RTC_STAT_REG, &rtc_ctrl);
@@ -308,6 +411,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       device_init_wakeup(&pdev->dev, true);
+
        rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops,
                        THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -316,8 +421,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
                return err;
        }
 
-       err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0,
-                                  "ab8500-rtc", rtc);
+       err = request_threaded_irq(irq, NULL, rtc_alarm_handler,
+               IRQF_NO_SUSPEND, "ab8500-rtc", rtc);
        if (err < 0) {
                rtc_device_unregister(rtc);
                return err;
@@ -325,6 +430,13 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, rtc);
 
+
+       err = ab8500_sysfs_rtc_register(&pdev->dev);
+       if (err) {
+               dev_err(&pdev->dev, "sysfs RTC failed to register\n");
+               return err;
+       }
+
        return 0;
 }
 
@@ -333,6 +445,8 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
        struct rtc_device *rtc = platform_get_drvdata(pdev);
        int irq = platform_get_irq_byname(pdev, "ALARM");
 
+       ab8500_sysfs_rtc_unregister(&pdev->dev);
+
        free_irq(irq, rtc);
        rtc_device_unregister(rtc);
        platform_set_drvdata(pdev, NULL);
@@ -349,18 +463,8 @@ static struct platform_driver ab8500_rtc_driver = {
        .remove = __devexit_p(ab8500_rtc_remove),
 };
 
-static int __init ab8500_rtc_init(void)
-{
-       return platform_driver_register(&ab8500_rtc_driver);
-}
-
-static void __exit ab8500_rtc_exit(void)
-{
-       platform_driver_unregister(&ab8500_rtc_driver);
-}
+module_platform_driver(ab8500_rtc_driver);
 
-module_init(ab8500_rtc_init);
-module_exit(ab8500_rtc_exit);
 MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>");
 MODULE_DESCRIPTION("AB8500 RTC Driver");
 MODULE_LICENSE("GPL v2");
index 90d8662..abfc1a0 100644 (file)
@@ -456,18 +456,7 @@ static struct platform_driver bfin_rtc_driver = {
        .resume         = bfin_rtc_resume,
 };
 
-static int __init bfin_rtc_init(void)
-{
-       return platform_driver_register(&bfin_rtc_driver);
-}
-
-static void __exit bfin_rtc_exit(void)
-{
-       platform_driver_unregister(&bfin_rtc_driver);
-}
-
-module_init(bfin_rtc_init);
-module_exit(bfin_rtc_exit);
+module_platform_driver(bfin_rtc_driver);
 
 MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver");
 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
index 128270c..bf612ef 100644 (file)
@@ -218,15 +218,4 @@ static struct platform_driver bq4802_driver = {
        .remove         = __devexit_p(bq4802_remove),
 };
 
-static int __init bq4802_init(void)
-{
-       return platform_driver_register(&bq4802_driver);
-}
-
-static void __exit bq4802_exit(void)
-{
-       platform_driver_unregister(&bq4802_driver);
-}
-
-module_init(bq4802_init);
-module_exit(bq4802_exit);
+module_platform_driver(bq4802_driver);
index 05beb6c..d7782aa 100644 (file)
@@ -164,7 +164,7 @@ static inline unsigned char cmos_read_bank2(unsigned char addr)
 static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
 {
        outb(addr, RTC_PORT(2));
-       outb(val, RTC_PORT(2));
+       outb(val, RTC_PORT(3));
 }
 
 #else
index 2322c43..d4457af 100644 (file)
@@ -161,16 +161,6 @@ static struct platform_driver rtc_dm355evm_driver = {
        },
 };
 
-static int __init dm355evm_rtc_init(void)
-{
-       return platform_driver_register(&rtc_dm355evm_driver);
-}
-module_init(dm355evm_rtc_init);
-
-static void __exit dm355evm_rtc_exit(void)
-{
-       platform_driver_unregister(&rtc_dm355evm_driver);
-}
-module_exit(dm355evm_rtc_exit);
+module_platform_driver(rtc_dm355evm_driver);
 
 MODULE_LICENSE("GPL");
index 68e6caf..990c3ff 100644 (file)
@@ -396,21 +396,10 @@ static struct platform_driver ds1286_platform_driver = {
        .remove         = __devexit_p(ds1286_remove),
 };
 
-static int __init ds1286_init(void)
-{
-       return platform_driver_register(&ds1286_platform_driver);
-}
-
-static void __exit ds1286_exit(void)
-{
-       platform_driver_unregister(&ds1286_platform_driver);
-}
+module_platform_driver(ds1286_platform_driver);
 
 MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
 MODULE_DESCRIPTION("DS1286 RTC driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_ALIAS("platform:rtc-ds1286");
-
-module_init(ds1286_init);
-module_exit(ds1286_exit);
index 586c244..761f36b 100644 (file)
@@ -580,20 +580,7 @@ static struct platform_driver ds1511_rtc_driver = {
        },
 };
 
- static int __init
-ds1511_rtc_init(void)
-{
-       return platform_driver_register(&ds1511_rtc_driver);
-}
-
- static void __exit
-ds1511_rtc_exit(void)
-{
-       platform_driver_unregister(&ds1511_rtc_driver);
-}
-
-module_init(ds1511_rtc_init);
-module_exit(ds1511_rtc_exit);
+module_platform_driver(ds1511_rtc_driver);
 
 MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>");
 MODULE_DESCRIPTION("Dallas DS1511 RTC driver");
index 1350029..6f0a1b5 100644 (file)
@@ -361,18 +361,7 @@ static struct platform_driver ds1553_rtc_driver = {
        },
 };
 
-static __init int ds1553_init(void)
-{
-       return platform_driver_register(&ds1553_rtc_driver);
-}
-
-static __exit void ds1553_exit(void)
-{
-       platform_driver_unregister(&ds1553_rtc_driver);
-}
-
-module_init(ds1553_init);
-module_exit(ds1553_exit);
+module_platform_driver(ds1553_rtc_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
index e3e0f92..7611266 100644 (file)
@@ -240,18 +240,7 @@ static struct platform_driver ds1742_rtc_driver = {
        },
 };
 
-static __init int ds1742_init(void)
-{
-       return platform_driver_register(&ds1742_rtc_driver);
-}
-
-static __exit void ds1742_exit(void)
-{
-       platform_driver_unregister(&ds1742_rtc_driver);
-}
-
-module_init(ds1742_init);
-module_exit(ds1742_exit);
+module_platform_driver(ds1742_rtc_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
index b647363..05ab227 100644 (file)
@@ -345,7 +345,7 @@ static const struct dev_pm_ops jz4740_pm_ops = {
 #define JZ4740_RTC_PM_OPS NULL
 #endif  /* CONFIG_PM */
 
-struct platform_driver jz4740_rtc_driver = {
+static struct platform_driver jz4740_rtc_driver = {
        .probe   = jz4740_rtc_probe,
        .remove  = __devexit_p(jz4740_rtc_remove),
        .driver  = {
@@ -355,17 +355,7 @@ struct platform_driver jz4740_rtc_driver = {
        },
 };
 
-static int __init jz4740_rtc_init(void)
-{
-       return platform_driver_register(&jz4740_rtc_driver);
-}
-module_init(jz4740_rtc_init);
-
-static void __exit jz4740_rtc_exit(void)
-{
-       platform_driver_unregister(&jz4740_rtc_driver);
-}
-module_exit(jz4740_rtc_exit);
+module_platform_driver(jz4740_rtc_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_LICENSE("GPL");
index ae16250..ecc1713 100644 (file)
@@ -396,17 +396,7 @@ static struct platform_driver lpc32xx_rtc_driver = {
        },
 };
 
-static int __init lpc32xx_rtc_init(void)
-{
-       return platform_driver_register(&lpc32xx_rtc_driver);
-}
-module_init(lpc32xx_rtc_init);
-
-static void __exit lpc32xx_rtc_exit(void)
-{
-       platform_driver_unregister(&lpc32xx_rtc_driver);
-}
-module_exit(lpc32xx_rtc_exit);
+module_platform_driver(lpc32xx_rtc_driver);
 
 MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com");
 MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC");
index 7317d3b..ef71132 100644 (file)
@@ -200,7 +200,6 @@ static int __devexit m41t93_remove(struct spi_device *spi)
 static struct spi_driver m41t93_driver = {
        .driver = {
                .name   = "rtc-m41t93",
-               .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
        },
        .probe  = m41t93_probe,
index e259ed7..2a4721f 100644 (file)
@@ -147,7 +147,6 @@ static int __devexit m41t94_remove(struct spi_device *spi)
 static struct spi_driver m41t94_driver = {
        .driver = {
                .name   = "rtc-m41t94",
-               .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
        },
        .probe  = m41t94_probe,
index 8e2a24e..f9e3b35 100644 (file)
@@ -216,21 +216,10 @@ static struct platform_driver m48t35_platform_driver = {
        .remove         = __devexit_p(m48t35_remove),
 };
 
-static int __init m48t35_init(void)
-{
-       return platform_driver_register(&m48t35_platform_driver);
-}
-
-static void __exit m48t35_exit(void)
-{
-       platform_driver_unregister(&m48t35_platform_driver);
-}
+module_platform_driver(m48t35_platform_driver);
 
 MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
 MODULE_DESCRIPTION("M48T35 RTC driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_ALIAS("platform:rtc-m48t35");
-
-module_init(m48t35_init);
-module_exit(m48t35_exit);
index 2836538..30ebfec 100644 (file)
@@ -530,18 +530,7 @@ static struct platform_driver m48t59_rtc_driver = {
        .remove         = __devexit_p(m48t59_rtc_remove),
 };
 
-static int __init m48t59_rtc_init(void)
-{
-       return platform_driver_register(&m48t59_rtc_driver);
-}
-
-static void __exit m48t59_rtc_exit(void)
-{
-       platform_driver_unregister(&m48t59_rtc_driver);
-}
-
-module_init(m48t59_rtc_init);
-module_exit(m48t59_rtc_exit);
+module_platform_driver(m48t59_rtc_driver);
 
 MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
 MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
index f981287..863fb33 100644 (file)
@@ -185,21 +185,10 @@ static struct platform_driver m48t86_rtc_platform_driver = {
        .remove         = __devexit_p(m48t86_rtc_remove),
 };
 
-static int __init m48t86_rtc_init(void)
-{
-       return platform_driver_register(&m48t86_rtc_platform_driver);
-}
-
-static void __exit m48t86_rtc_exit(void)
-{
-       platform_driver_unregister(&m48t86_rtc_platform_driver);
-}
+module_platform_driver(m48t86_rtc_platform_driver);
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
 MODULE_DESCRIPTION("M48T86 RTC driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_ALIAS("platform:rtc-m48t86");
-
-module_init(m48t86_rtc_init);
-module_exit(m48t86_rtc_exit);
index 0ec3f58..1f6b3cc 100644 (file)
@@ -154,7 +154,6 @@ static int __devexit max6902_remove(struct spi_device *spi)
 static struct spi_driver max6902_driver = {
        .driver = {
                .name   = "rtc-max6902",
-               .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
        },
        .probe  = max6902_probe,
index 3bc046f..4a55293 100644 (file)
@@ -299,17 +299,7 @@ static struct platform_driver max8925_rtc_driver = {
        .remove         = __devexit_p(max8925_rtc_remove),
 };
 
-static int __init max8925_rtc_init(void)
-{
-       return platform_driver_register(&max8925_rtc_driver);
-}
-module_init(max8925_rtc_init);
-
-static void __exit max8925_rtc_exit(void)
-{
-       platform_driver_unregister(&max8925_rtc_driver);
-}
-module_exit(max8925_rtc_exit);
+module_platform_driver(max8925_rtc_driver);
 
 MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index 2e48aa6..7196f43 100644 (file)
@@ -327,17 +327,7 @@ static struct platform_driver max8998_rtc_driver = {
        .id_table       = max8998_rtc_id,
 };
 
-static int __init max8998_rtc_init(void)
-{
-       return platform_driver_register(&max8998_rtc_driver);
-}
-module_init(max8998_rtc_init);
-
-static void __exit max8998_rtc_exit(void)
-{
-       platform_driver_unregister(&max8998_rtc_driver);
-}
-module_exit(max8998_rtc_exit);
+module_platform_driver(max8998_rtc_driver);
 
 MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
index 9d0c3b4..546f685 100644 (file)
@@ -399,7 +399,7 @@ static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
-const struct platform_device_id mc13xxx_rtc_idtable[] = {
+static const struct platform_device_id mc13xxx_rtc_idtable[] = {
        {
                .name = "mc13783-rtc",
        }, {
index da60915..9d3cacc 100644 (file)
@@ -418,17 +418,7 @@ static struct platform_driver mpc5121_rtc_driver = {
        .remove = __devexit_p(mpc5121_rtc_remove),
 };
 
-static int __init mpc5121_rtc_init(void)
-{
-       return platform_driver_register(&mpc5121_rtc_driver);
-}
-module_init(mpc5121_rtc_init);
-
-static void __exit mpc5121_rtc_exit(void)
-{
-       platform_driver_unregister(&mpc5121_rtc_driver);
-}
-module_exit(mpc5121_rtc_exit);
+module_platform_driver(mpc5121_rtc_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>");
index bb21f44..6cd6c72 100644 (file)
@@ -537,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = {
        }
 };
 
-static int __init vrtc_mrst_init(void)
-{
-       return platform_driver_register(&vrtc_mrst_platform_driver);
-}
-
-static void __exit vrtc_mrst_exit(void)
-{
-       platform_driver_unregister(&vrtc_mrst_platform_driver);
-}
-
-module_init(vrtc_mrst_init);
-module_exit(vrtc_mrst_exit);
+module_platform_driver(vrtc_mrst_platform_driver);
 
 MODULE_AUTHOR("Jacob Pan; Feng Tang");
 MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
index 39e41fb..5e1d64e 100644 (file)
@@ -155,7 +155,6 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
 {
        struct rtc_time alarm_tm, now_tm;
        unsigned long now, time;
-       int ret;
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        void __iomem *ioaddr = pdata->ioaddr;
@@ -168,21 +167,33 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
        alarm_tm.tm_hour = alrm->tm_hour;
        alarm_tm.tm_min = alrm->tm_min;
        alarm_tm.tm_sec = alrm->tm_sec;
-       rtc_tm_to_time(&now_tm, &now);
        rtc_tm_to_time(&alarm_tm, &time);
 
-       if (time < now) {
-               time += 60 * 60 * 24;
-               rtc_time_to_tm(time, &alarm_tm);
-       }
-
-       ret = rtc_tm_to_time(&alarm_tm, &time);
-
        /* clear all the interrupt status bits */
        writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR);
        set_alarm_or_time(dev, MXC_RTC_ALARM, time);
 
-       return ret;
+       return 0;
+}
+
+static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
+                               unsigned int enabled)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       u32 reg;
+
+       spin_lock_irq(&pdata->rtc->irq_lock);
+       reg = readw(ioaddr + RTC_RTCIENR);
+
+       if (enabled)
+               reg |= bit;
+       else
+               reg &= ~bit;
+
+       writew(reg, ioaddr + RTC_RTCIENR);
+       spin_unlock_irq(&pdata->rtc->irq_lock);
 }
 
 /* This function is the RTC interrupt service routine. */
@@ -199,13 +210,12 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
        /* clear interrupt sources */
        writew(status, ioaddr + RTC_RTCISR);
 
-       /* clear alarm interrupt if it has occurred */
-       if (status & RTC_ALM_BIT)
-               status &= ~RTC_ALM_BIT;
-
        /* update irq data & counter */
-       if (status & RTC_ALM_BIT)
+       if (status & RTC_ALM_BIT) {
                events |= (RTC_AF | RTC_IRQF);
+               /* RTC alarm should be one-shot */
+               mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0);
+       }
 
        if (status & RTC_1HZ_BIT)
                events |= (RTC_UF | RTC_IRQF);
@@ -213,9 +223,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
        if (status & PIT_ALL_ON)
                events |= (RTC_PF | RTC_IRQF);
 
-       if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm))
-               rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm);
-
        rtc_update_irq(pdata->rtc, 1, events);
        spin_unlock_irq(&pdata->rtc->irq_lock);
 
@@ -242,26 +249,6 @@ static void mxc_rtc_release(struct device *dev)
        spin_unlock_irq(&pdata->rtc->irq_lock);
 }
 
-static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
-                               unsigned int enabled)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       void __iomem *ioaddr = pdata->ioaddr;
-       u32 reg;
-
-       spin_lock_irq(&pdata->rtc->irq_lock);
-       reg = readw(ioaddr + RTC_RTCIENR);
-
-       if (enabled)
-               reg |= bit;
-       else
-               reg &= ~bit;
-
-       writew(reg, ioaddr + RTC_RTCIENR);
-       spin_unlock_irq(&pdata->rtc->irq_lock);
-}
-
 static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled);
@@ -290,6 +277,17 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
  */
 static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
 {
+       /*
+        * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
+        */
+       if (cpu_is_mx1()) {
+               struct rtc_time tm;
+
+               rtc_time_to_tm(time, &tm);
+               tm.tm_year = 70;
+               rtc_tm_to_time(&tm, &time);
+       }
+
        /* Avoid roll-over from reading the different registers */
        do {
                set_alarm_or_time(dev, MXC_RTC_TIME, time);
@@ -324,21 +322,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        int ret;
 
-       if (rtc_valid_tm(&alrm->time)) {
-               if (alrm->time.tm_sec > 59 ||
-                   alrm->time.tm_hour > 23 ||
-                   alrm->time.tm_min > 59)
-                       return -EINVAL;
-
-               ret = rtc_update_alarm(dev, &alrm->time);
-       } else {
-               ret = rtc_valid_tm(&alrm->time);
-               if (ret)
-                       return ret;
-
-               ret = rtc_update_alarm(dev, &alrm->time);
-       }
-
+       ret = rtc_update_alarm(dev, &alrm->time);
        if (ret)
                return ret;
 
@@ -424,6 +408,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
                pdata->irq = -1;
        }
 
+       if (pdata->irq >=0)
+               device_init_wakeup(&pdev->dev, 1);
+
        rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
                                  THIS_MODULE);
        if (IS_ERR(rtc)) {
@@ -459,9 +446,39 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int mxc_rtc_suspend(struct device *dev)
+{
+       struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(pdata->irq);
+
+       return 0;
+}
+
+static int mxc_rtc_resume(struct device *dev)
+{
+       struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(pdata->irq);
+
+       return 0;
+}
+
+static struct dev_pm_ops mxc_rtc_pm_ops = {
+       .suspend        = mxc_rtc_suspend,
+       .resume         = mxc_rtc_resume,
+};
+#endif
+
 static struct platform_driver mxc_rtc_driver = {
        .driver = {
                   .name        = "mxc_rtc",
+#ifdef CONFIG_PM
+                  .pm          = &mxc_rtc_pm_ops,
+#endif
                   .owner       = THIS_MODULE,
        },
        .remove         = __exit_p(mxc_rtc_remove),
index 2ee3bbf..b46c400 100644 (file)
@@ -340,7 +340,6 @@ static int __devexit pcf2123_remove(struct spi_device *spi)
 static struct spi_driver pcf2123_driver = {
        .driver = {
                        .name   = "rtc-pcf2123",
-                       .bus    = &spi_bus_type,
                        .owner  = THIS_MODULE,
        },
        .probe  = pcf2123_probe,
index 0c42389..a20202f 100644 (file)
@@ -294,17 +294,7 @@ static struct platform_driver pcf50633_rtc_driver = {
        .remove = __devexit_p(pcf50633_rtc_remove),
 };
 
-static int __init pcf50633_rtc_init(void)
-{
-       return platform_driver_register(&pcf50633_rtc_driver);
-}
-module_init(pcf50633_rtc_init);
-
-static void __exit pcf50633_rtc_exit(void)
-{
-       platform_driver_unregister(&pcf50633_rtc_driver);
-}
-module_exit(pcf50633_rtc_exit);
+module_platform_driver(pcf50633_rtc_driver);
 
 MODULE_DESCRIPTION("PCF50633 RTC driver");
 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
index d420e9d..9f1d6bc 100644 (file)
@@ -532,17 +532,7 @@ static struct platform_driver pm8xxx_rtc_driver = {
        },
 };
 
-static int __init pm8xxx_rtc_init(void)
-{
-       return platform_driver_register(&pm8xxx_rtc_driver);
-}
-module_init(pm8xxx_rtc_init);
-
-static void __exit pm8xxx_rtc_exit(void)
-{
-       platform_driver_unregister(&pm8xxx_rtc_driver);
-}
-module_exit(pm8xxx_rtc_exit);
+module_platform_driver(pm8xxx_rtc_driver);
 
 MODULE_ALIAS("platform:rtc-pm8xxx");
 MODULE_DESCRIPTION("PMIC8xxx RTC driver");
index 971bc8e..ce2ca85 100644 (file)
@@ -229,7 +229,6 @@ static int __devexit rs5c348_remove(struct spi_device *spi)
 static struct spi_driver rs5c348_driver = {
        .driver = {
                .name   = "rtc-rs5c348",
-               .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
        },
        .probe  = rs5c348_probe,
index 175067a..aef40bd 100644 (file)
@@ -673,21 +673,7 @@ static struct platform_driver s3c_rtc_driver = {
        },
 };
 
-static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
-
-static int __init s3c_rtc_init(void)
-{
-       printk(banner);
-       return platform_driver_register(&s3c_rtc_driver);
-}
-
-static void __exit s3c_rtc_exit(void)
-{
-       platform_driver_unregister(&s3c_rtc_driver);
-}
-
-module_init(s3c_rtc_init);
-module_exit(s3c_rtc_exit);
+module_platform_driver(s3c_rtc_driver);
 
 MODULE_DESCRIPTION("Samsung S3C RTC Driver");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
index fc1ffe9..4595d3e 100644 (file)
@@ -435,18 +435,7 @@ static struct platform_driver sa1100_rtc_driver = {
        },
 };
 
-static int __init sa1100_rtc_init(void)
-{
-       return platform_driver_register(&sa1100_rtc_driver);
-}
-
-static void __exit sa1100_rtc_exit(void)
-{
-       platform_driver_unregister(&sa1100_rtc_driver);
-}
-
-module_init(sa1100_rtc_init);
-module_exit(sa1100_rtc_exit);
+module_platform_driver(sa1100_rtc_driver);
 
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
 MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
index 893bac2..19a28a6 100644 (file)
@@ -516,17 +516,7 @@ static struct platform_driver spear_rtc_driver = {
        },
 };
 
-static int __init rtc_init(void)
-{
-       return platform_driver_register(&spear_rtc_driver);
-}
-module_init(rtc_init);
-
-static void __exit rtc_exit(void)
-{
-       platform_driver_unregister(&spear_rtc_driver);
-}
-module_exit(rtc_exit);
+module_platform_driver(spear_rtc_driver);
 
 MODULE_ALIAS("platform:rtc-spear");
 MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
index ed3e9b5..7621116 100644 (file)
@@ -370,18 +370,7 @@ static struct platform_driver stk17ta8_rtc_driver = {
        },
 };
 
-static __init int stk17ta8_init(void)
-{
-       return platform_driver_register(&stk17ta8_rtc_driver);
-}
-
-static __exit void stk17ta8_exit(void)
-{
-       platform_driver_unregister(&stk17ta8_rtc_driver);
-}
-
-module_init(stk17ta8_init);
-module_exit(stk17ta8_exit);
+module_platform_driver(stk17ta8_rtc_driver);
 
 MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>");
 MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver");
index 7315068..1028786 100644 (file)
@@ -276,18 +276,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
        },
 };
 
-static int __init stmp3xxx_rtc_init(void)
-{
-       return platform_driver_register(&stmp3xxx_rtcdrv);
-}
-
-static void __exit stmp3xxx_rtc_exit(void)
-{
-       platform_driver_unregister(&stmp3xxx_rtcdrv);
-}
-
-module_init(stmp3xxx_rtc_init);
-module_exit(stmp3xxx_rtc_exit);
+module_platform_driver(stmp3xxx_rtcdrv);
 
 MODULE_DESCRIPTION("STMP3xxx RTC Driver");
 MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
index 20687d5..d43b4f6 100644 (file)
@@ -550,6 +550,11 @@ static int twl_rtc_resume(struct platform_device *pdev)
 #define twl_rtc_resume  NULL
 #endif
 
+static const struct of_device_id twl_rtc_of_match[] = {
+       {.compatible = "ti,twl4030-rtc", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl_rtc_of_match);
 MODULE_ALIAS("platform:twl_rtc");
 
 static struct platform_driver twl4030rtc_driver = {
@@ -559,8 +564,9 @@ static struct platform_driver twl4030rtc_driver = {
        .suspend        = twl_rtc_suspend,
        .resume         = twl_rtc_resume,
        .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "twl_rtc",
+               .owner          = THIS_MODULE,
+               .name           = "twl_rtc",
+               .of_match_table = twl_rtc_of_match,
        },
 };
 
index f71c3ce..bca5d67 100644 (file)
@@ -393,18 +393,7 @@ static struct platform_driver rtc_device_driver = {
        },
 };
 
-static __init int v3020_init(void)
-{
-       return platform_driver_register(&rtc_device_driver);
-}
-
-static __exit void v3020_exit(void)
-{
-       platform_driver_unregister(&rtc_device_driver);
-}
-
-module_init(v3020_init);
-module_exit(v3020_exit);
+module_platform_driver(rtc_device_driver);
 
 MODULE_DESCRIPTION("V3020 RTC");
 MODULE_AUTHOR("Raphael Assenat");
index c5698cd..fcbfdda 100644 (file)
@@ -405,15 +405,4 @@ static struct platform_driver rtc_platform_driver = {
        },
 };
 
-static int __init vr41xx_rtc_init(void)
-{
-       return platform_driver_register(&rtc_platform_driver);
-}
-
-static void __exit vr41xx_rtc_exit(void)
-{
-       platform_driver_unregister(&rtc_platform_driver);
-}
-
-module_init(vr41xx_rtc_init);
-module_exit(vr41xx_rtc_exit);
+module_platform_driver(rtc_platform_driver);
index f93f412..9e94fb1 100644 (file)
@@ -311,17 +311,7 @@ static struct platform_driver vt8500_rtc_driver = {
        },
 };
 
-static int __init vt8500_rtc_init(void)
-{
-       return platform_driver_register(&vt8500_rtc_driver);
-}
-module_init(vt8500_rtc_init);
-
-static void __exit vt8500_rtc_exit(void)
-{
-       platform_driver_unregister(&vt8500_rtc_driver);
-}
-module_exit(vt8500_rtc_exit);
+module_platform_driver(vt8500_rtc_driver);
 
 MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
 MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)");
index bdc909b..3b6e6a6 100644 (file)
@@ -324,15 +324,6 @@ static irqreturn_t wm831x_alm_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t wm831x_per_irq(int irq, void *data)
-{
-       struct wm831x_rtc *wm831x_rtc = data;
-
-       rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF);
-
-       return IRQ_HANDLED;
-}
-
 static const struct rtc_class_ops wm831x_rtc_ops = {
        .read_time = wm831x_rtc_readtime,
        .set_mmss = wm831x_rtc_set_mmss,
@@ -405,11 +396,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_rtc *wm831x_rtc;
-       int per_irq = platform_get_irq_byname(pdev, "PER");
        int alm_irq = platform_get_irq_byname(pdev, "ALM");
        int ret = 0;
 
-       wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL);
+       wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL);
        if (wm831x_rtc == NULL)
                return -ENOMEM;
 
@@ -433,14 +423,6 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq,
-                                  IRQF_TRIGGER_RISING, "RTC period",
-                                  wm831x_rtc);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
-                       per_irq, ret);
-       }
-
        ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq,
                                   IRQF_TRIGGER_RISING, "RTC alarm",
                                   wm831x_rtc);
@@ -452,20 +434,16 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
        return 0;
 
 err:
-       kfree(wm831x_rtc);
        return ret;
 }
 
 static int __devexit wm831x_rtc_remove(struct platform_device *pdev)
 {
        struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev);
-       int per_irq = platform_get_irq_byname(pdev, "PER");
        int alm_irq = platform_get_irq_byname(pdev, "ALM");
 
        free_irq(alm_irq, wm831x_rtc);
-       free_irq(per_irq, wm831x_rtc);
        rtc_device_unregister(wm831x_rtc->rtc);
-       kfree(wm831x_rtc);
 
        return 0;
 }
@@ -490,17 +468,7 @@ static struct platform_driver wm831x_rtc_driver = {
        },
 };
 
-static int __init wm831x_rtc_init(void)
-{
-       return platform_driver_register(&wm831x_rtc_driver);
-}
-module_init(wm831x_rtc_init);
-
-static void __exit wm831x_rtc_exit(void)
-{
-       platform_driver_unregister(&wm831x_rtc_driver);
-}
-module_exit(wm831x_rtc_exit);
+module_platform_driver(wm831x_rtc_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs");
index 6642142..c2e52d1 100644 (file)
@@ -486,17 +486,7 @@ static struct platform_driver wm8350_rtc_driver = {
        },
 };
 
-static int __init wm8350_rtc_init(void)
-{
-       return platform_driver_register(&wm8350_rtc_driver);
-}
-module_init(wm8350_rtc_init);
-
-static void __exit wm8350_rtc_exit(void)
-{
-       platform_driver_unregister(&wm8350_rtc_driver);
-}
-module_exit(wm8350_rtc_exit);
+module_platform_driver(wm8350_rtc_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("RTC driver for the WM8350");
index 1105fa1..a1376dc 100644 (file)
@@ -270,17 +270,7 @@ static struct platform_driver pm860x_backlight_driver = {
        .remove         = pm860x_backlight_remove,
 };
 
-static int __init pm860x_backlight_init(void)
-{
-       return platform_driver_register(&pm860x_backlight_driver);
-}
-module_init(pm860x_backlight_init);
-
-static void __exit pm860x_backlight_exit(void)
-{
-       platform_driver_unregister(&pm860x_backlight_driver);
-}
-module_exit(pm860x_backlight_exit);
+module_platform_driver(pm860x_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index 278aeaa..681b369 100644 (file)
@@ -280,14 +280,6 @@ config BACKLIGHT_WM831X
          If you have a backlight driven by the ISINK and DCDC of a
          WM831x PMIC say y to enable the backlight driver for it.
 
-config BACKLIGHT_ADX
-       tristate "Avionic Design Xanthos Backlight Driver"
-       depends on ARCH_PXA_ADX
-       default y
-       help
-         Say Y to enable the backlight driver on Avionic Design Xanthos-based
-         boards.
-
 config BACKLIGHT_ADP5520
        tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
        depends on PMIC_ADP5520
index fdd1fc4..af5cf65 100644 (file)
@@ -32,7 +32,6 @@ obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
-obj-$(CONFIG_BACKLIGHT_ADX)    += adx_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP5520)        += adp5520_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP8860)        += adp8860_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP8870)        += adp8870_bl.o
index dfb763e..2e630bf 100644 (file)
@@ -384,17 +384,7 @@ static struct platform_driver adp5520_bl_driver = {
        .resume         = adp5520_bl_resume,
 };
 
-static int __init adp5520_bl_init(void)
-{
-       return platform_driver_register(&adp5520_bl_driver);
-}
-module_init(adp5520_bl_init);
-
-static void __exit adp5520_bl_exit(void)
-{
-       platform_driver_unregister(&adp5520_bl_driver);
-}
-module_exit(adp5520_bl_exit);
+module_platform_driver(adp5520_bl_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("ADP5520(01) Backlight Driver");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
deleted file mode 100644 (file)
index c861c41..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * linux/drivers/video/backlight/adx.c
- *
- * Copyright (C) 2009 Avionic Design GmbH
- *
- * 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.
- *
- * Written by Thierry Reding <thierry.reding@avionic-design.de>
- */
-
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-/* register definitions */
-#define ADX_BACKLIGHT_CONTROL          0x00
-#define ADX_BACKLIGHT_CONTROL_ENABLE   (1 << 0)
-#define ADX_BACKLIGHT_BRIGHTNESS       0x08
-#define ADX_BACKLIGHT_STATUS           0x10
-#define ADX_BACKLIGHT_ERROR            0x18
-
-struct adxbl {
-       void __iomem *base;
-};
-
-static int adx_backlight_update_status(struct backlight_device *bldev)
-{
-       struct adxbl *bl = bl_get_data(bldev);
-       u32 value;
-
-       value = bldev->props.brightness;
-       writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS);
-
-       value = readl(bl->base + ADX_BACKLIGHT_CONTROL);
-
-       if (bldev->props.state & BL_CORE_FBBLANK)
-               value &= ~ADX_BACKLIGHT_CONTROL_ENABLE;
-       else
-               value |= ADX_BACKLIGHT_CONTROL_ENABLE;
-
-       writel(value, bl->base + ADX_BACKLIGHT_CONTROL);
-
-       return 0;
-}
-
-static int adx_backlight_get_brightness(struct backlight_device *bldev)
-{
-       struct adxbl *bl = bl_get_data(bldev);
-       u32 brightness;
-
-       brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS);
-       return brightness & 0xff;
-}
-
-static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb)
-{
-       return 1;
-}
-
-static const struct backlight_ops adx_backlight_ops = {
-       .options = 0,
-       .update_status = adx_backlight_update_status,
-       .get_brightness = adx_backlight_get_brightness,
-       .check_fb = adx_backlight_check_fb,
-};
-
-static int __devinit adx_backlight_probe(struct platform_device *pdev)
-{
-       struct backlight_properties props;
-       struct backlight_device *bldev;
-       struct resource *res;
-       struct adxbl *bl;
-       int ret = 0;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENXIO;
-               goto out;
-       }
-
-       res = devm_request_mem_region(&pdev->dev, res->start,
-                       resource_size(res), res->name);
-       if (!res) {
-               ret = -ENXIO;
-               goto out;
-       }
-
-       bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
-       if (!bl) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       bl->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                       resource_size(res));
-       if (!bl->base) {
-               ret = -ENXIO;
-               goto out;
-       }
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_RAW;
-       props.max_brightness = 0xff;
-       bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
-                                         bl, &adx_backlight_ops, &props);
-       if (IS_ERR(bldev)) {
-               ret = PTR_ERR(bldev);
-               goto out;
-       }
-
-       bldev->props.brightness = 0xff;
-       bldev->props.power = FB_BLANK_UNBLANK;
-
-       platform_set_drvdata(pdev, bldev);
-
-out:
-       return ret;
-}
-
-static int __devexit adx_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bldev;
-       int ret = 0;
-
-       bldev = platform_get_drvdata(pdev);
-       bldev->props.power = FB_BLANK_UNBLANK;
-       bldev->props.brightness = 0xff;
-       backlight_update_status(bldev);
-       backlight_device_unregister(bldev);
-       platform_set_drvdata(pdev, NULL);
-
-       return ret;
-}
-
-#ifdef CONFIG_PM
-static int adx_backlight_suspend(struct platform_device *pdev,
-               pm_message_t state)
-{
-       return 0;
-}
-
-static int adx_backlight_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-#else
-#define adx_backlight_suspend NULL
-#define adx_backlight_resume NULL
-#endif
-
-static struct platform_driver adx_backlight_driver = {
-       .probe = adx_backlight_probe,
-       .remove = __devexit_p(adx_backlight_remove),
-       .suspend = adx_backlight_suspend,
-       .resume = adx_backlight_resume,
-       .driver = {
-               .name = "adx-backlight",
-               .owner = THIS_MODULE,
-       },
-};
-
-static int __init adx_backlight_init(void)
-{
-       return platform_driver_register(&adx_backlight_driver);
-}
-
-static void __exit adx_backlight_exit(void)
-{
-       platform_driver_unregister(&adx_backlight_driver);
-}
-
-module_init(adx_backlight_init);
-module_exit(adx_backlight_exit);
-
-MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver");
-MODULE_LICENSE("GPL v2");
index 7363c1b..bf5b1ec 100644 (file)
@@ -102,7 +102,7 @@ static void backlight_generate_event(struct backlight_device *bd,
 }
 
 static ssize_t backlight_show_power(struct device *dev,
-               struct device_attribute *attr,char *buf)
+               struct device_attribute *attr, char *buf)
 {
        struct backlight_device *bd = to_backlight_device(dev);
 
@@ -116,7 +116,7 @@ static ssize_t backlight_store_power(struct device *dev,
        struct backlight_device *bd = to_backlight_device(dev);
        unsigned long power;
 
-       rc = strict_strtoul(buf, 0, &power);
+       rc = kstrtoul(buf, 0, &power);
        if (rc)
                return rc;
 
@@ -150,7 +150,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
        struct backlight_device *bd = to_backlight_device(dev);
        unsigned long brightness;
 
-       rc = strict_strtoul(buf, 0, &brightness);
+       rc = kstrtoul(buf, 0, &brightness);
        if (rc)
                return rc;
 
index d68f14b..abb4a06 100644 (file)
@@ -199,17 +199,7 @@ static struct platform_driver da903x_backlight_driver = {
        .remove         = da903x_backlight_remove,
 };
 
-static int __init da903x_backlight_init(void)
-{
-       return platform_driver_register(&da903x_backlight_driver);
-}
-module_init(da903x_backlight_init);
-
-static void __exit da903x_backlight_exit(void)
-{
-       platform_driver_unregister(&da903x_backlight_driver);
-}
-module_exit(da903x_backlight_exit);
+module_platform_driver(da903x_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
 MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
index c74a6f4..b62b8b9 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/fb.h>
 #include <linux/backlight.h>
@@ -144,17 +143,7 @@ static struct platform_driver ep93xxbl_driver = {
        .resume         = ep93xxbl_resume,
 };
 
-static int __init ep93xxbl_init(void)
-{
-       return platform_driver_register(&ep93xxbl_driver);
-}
-module_init(ep93xxbl_init);
-
-static void __exit ep93xxbl_exit(void)
-{
-       platform_driver_unregister(&ep93xxbl_driver);
-}
-module_exit(ep93xxbl_exit);
+module_platform_driver(ep93xxbl_driver);
 
 MODULE_DESCRIPTION("EP93xx Backlight Driver");
 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
index adb1914..9ce6170 100644 (file)
@@ -132,18 +132,7 @@ static struct platform_driver genericbl_driver = {
        },
 };
 
-static int __init genericbl_init(void)
-{
-       return platform_driver_register(&genericbl_driver);
-}
-
-static void __exit genericbl_exit(void)
-{
-       platform_driver_unregister(&genericbl_driver);
-}
-
-module_init(genericbl_init);
-module_exit(genericbl_exit);
+module_platform_driver(genericbl_driver);
 
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
 MODULE_DESCRIPTION("Generic Backlight Driver");
index de65d80..2f8af5d 100644 (file)
@@ -147,19 +147,8 @@ static struct platform_driver jornada_bl_driver = {
        },
 };
 
-static int __init jornada_bl_init(void)
-{
-       return platform_driver_register(&jornada_bl_driver);
-}
-
-static void __exit jornada_bl_exit(void)
-{
-       platform_driver_unregister(&jornada_bl_driver);
-}
+module_platform_driver(jornada_bl_driver);
 
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
 MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
 MODULE_LICENSE("GPL");
-
-module_init(jornada_bl_init);
-module_exit(jornada_bl_exit);
index d2ff658..22d231a 100644 (file)
@@ -135,19 +135,8 @@ static struct platform_driver jornada_lcd_driver = {
        },
 };
 
-static int __init jornada_lcd_init(void)
-{
-       return platform_driver_register(&jornada_lcd_driver);
-}
-
-static void __exit jornada_lcd_exit(void)
-{
-       platform_driver_unregister(&jornada_lcd_driver);
-}
+module_platform_driver(jornada_lcd_driver);
 
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver");
 MODULE_LICENSE("GPL");
-
-module_init(jornada_lcd_init);
-module_exit(jornada_lcd_exit);
index 71a11ca..79c1b0d 100644 (file)
@@ -97,19 +97,16 @@ static ssize_t lcd_store_power(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        int rc = -ENXIO;
-       char *endp;
        struct lcd_device *ld = to_lcd_device(dev);
-       int power = simple_strtoul(buf, &endp, 0);
-       size_t size = endp - buf;
+       unsigned long power;
 
-       if (isspace(*endp))
-               size++;
-       if (size != count)
-               return -EINVAL;
+       rc = kstrtoul(buf, 0, &power);
+       if (rc)
+               return rc;
 
        mutex_lock(&ld->ops_lock);
        if (ld->ops && ld->ops->set_power) {
-               pr_debug("lcd: set power to %d\n", power);
+               pr_debug("lcd: set power to %lu\n", power);
                ld->ops->set_power(ld, power);
                rc = count;
        }
@@ -136,19 +133,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        int rc = -ENXIO;
-       char *endp;
        struct lcd_device *ld = to_lcd_device(dev);
-       int contrast = simple_strtoul(buf, &endp, 0);
-       size_t size = endp - buf;
+       unsigned long contrast;
 
-       if (isspace(*endp))
-               size++;
-       if (size != count)
-               return -EINVAL;
+       rc = kstrtoul(buf, 0, &contrast);
+       if (rc)
+               return rc;
 
        mutex_lock(&ld->ops_lock);
        if (ld->ops && ld->ops->set_contrast) {
-               pr_debug("lcd: set contrast to %d\n", contrast);
+               pr_debug("lcd: set contrast to %lu\n", contrast);
                ld->ops->set_contrast(ld, contrast);
                rc = count;
        }
index da9a5ce..78dafc0 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/lcd.h>
 #include <linux/backlight.h>
 #include <linux/module.h>
+#include <linux/regulator/consumer.h>
 
 #include "ld9040_gamma.h"
 
@@ -53,8 +54,51 @@ struct ld9040 {
        struct lcd_device               *ld;
        struct backlight_device         *bd;
        struct lcd_platform_data        *lcd_pd;
+
+       struct mutex                    lock;
+       bool  enabled;
+};
+
+static struct regulator_bulk_data supplies[] = {
+       { .supply = "vdd3", },
+       { .supply = "vci", },
 };
 
+static void ld9040_regulator_enable(struct ld9040 *lcd)
+{
+       int ret = 0;
+       struct lcd_platform_data *pd = NULL;
+
+       pd = lcd->lcd_pd;
+       mutex_lock(&lcd->lock);
+       if (!lcd->enabled) {
+               ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+               if (ret)
+                       goto out;
+
+               lcd->enabled = true;
+       }
+       mdelay(pd->power_on_delay);
+out:
+       mutex_unlock(&lcd->lock);
+}
+
+static void ld9040_regulator_disable(struct ld9040 *lcd)
+{
+       int ret = 0;
+
+       mutex_lock(&lcd->lock);
+       if (lcd->enabled) {
+               ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+               if (ret)
+                       goto out;
+
+               lcd->enabled = false;
+       }
+out:
+       mutex_unlock(&lcd->lock);
+}
+
 static const unsigned short seq_swreset[] = {
        0x01, COMMAND_ONLY,
        ENDDEF, 0x00
@@ -532,13 +576,8 @@ static int ld9040_power_on(struct ld9040 *lcd)
                return -EFAULT;
        }
 
-       if (!pd->power_on) {
-               dev_err(lcd->dev, "power_on is NULL.\n");
-               return -EFAULT;
-       } else {
-               pd->power_on(lcd->ld, 1);
-               mdelay(pd->power_on_delay);
-       }
+       /* lcd power on */
+       ld9040_regulator_enable(lcd);
 
        if (!pd->reset) {
                dev_err(lcd->dev, "reset is NULL.\n");
@@ -582,11 +621,8 @@ static int ld9040_power_off(struct ld9040 *lcd)
 
        mdelay(pd->power_off_delay);
 
-       if (!pd->power_on) {
-               dev_err(lcd->dev, "power_on is NULL.\n");
-               return -EFAULT;
-       } else
-               pd->power_on(lcd->ld, 0);
+       /* lcd power off */
+       ld9040_regulator_disable(lcd);
 
        return 0;
 }
@@ -693,6 +729,14 @@ static int ld9040_probe(struct spi_device *spi)
                goto out_free_lcd;
        }
 
+       mutex_init(&lcd->lock);
+
+       ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
+       if (ret) {
+               dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
+               goto out_free_lcd;
+       }
+
        ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
        if (IS_ERR(ld)) {
                ret = PTR_ERR(ld);
@@ -739,6 +783,8 @@ static int ld9040_probe(struct spi_device *spi)
 out_unregister_lcd:
        lcd_device_unregister(lcd->ld);
 out_free_lcd:
+       regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+
        kfree(lcd);
        return ret;
 }
@@ -750,6 +796,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
        ld9040_power(lcd, FB_BLANK_POWERDOWN);
        backlight_device_unregister(lcd->bd);
        lcd_device_unregister(lcd->ld);
+       regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
        kfree(lcd);
 
        return 0;
index 7bbc802..c915e3b 100644 (file)
@@ -188,17 +188,7 @@ static struct platform_driver max8925_backlight_driver = {
        .remove         = __devexit_p(max8925_backlight_remove),
 };
 
-static int __init max8925_backlight_init(void)
-{
-       return platform_driver_register(&max8925_backlight_driver);
-}
-module_init(max8925_backlight_init);
-
-static void __exit max8925_backlight_exit(void)
-{
-       platform_driver_unregister(&max8925_backlight_driver);
-};
-module_exit(max8925_backlight_exit);
+module_platform_driver(max8925_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index 08d26a7..d8cde27 100644 (file)
@@ -195,18 +195,7 @@ static struct platform_driver omapbl_driver = {
        },
 };
 
-static int __init omapbl_init(void)
-{
-       return platform_driver_register(&omapbl_driver);
-}
-
-static void __exit omapbl_exit(void)
-{
-       platform_driver_unregister(&omapbl_driver);
-}
-
-module_init(omapbl_init);
-module_exit(omapbl_exit);
+module_platform_driver(omapbl_driver);
 
 MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>");
 MODULE_DESCRIPTION("OMAP LCD Backlight driver");
index ef5628d..13e88b7 100644 (file)
@@ -173,17 +173,7 @@ static struct platform_driver pcf50633_bl_driver = {
        },
 };
 
-static int __init pcf50633_bl_init(void)
-{
-       return platform_driver_register(&pcf50633_bl_driver);
-}
-module_init(pcf50633_bl_init);
-
-static void __exit pcf50633_bl_exit(void)
-{
-       platform_driver_unregister(&pcf50633_bl_driver);
-}
-module_exit(pcf50633_bl_exit);
+module_platform_driver(pcf50633_bl_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("PCF50633 backlight driver");
index 302330a..f0bf491 100644 (file)
@@ -85,7 +85,8 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+       plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd),
+                           GFP_KERNEL);
        if (!plcd) {
                dev_err(dev, "no memory for state\n");
                return -ENOMEM;
@@ -98,7 +99,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
        if (IS_ERR(plcd->lcd)) {
                dev_err(dev, "cannot register lcd device\n");
                err = PTR_ERR(plcd->lcd);
-               goto err_mem;
+               goto err;
        }
 
        platform_set_drvdata(pdev, plcd);
@@ -106,8 +107,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
 
        return 0;
 
- err_mem:
-       kfree(plcd);
+ err:
        return err;
 }
 
@@ -116,7 +116,6 @@ static int __devexit platform_lcd_remove(struct platform_device *pdev)
        struct platform_lcd *plcd = platform_get_drvdata(pdev);
 
        lcd_device_unregister(plcd->lcd);
-       kfree(plcd);
 
        return 0;
 }
@@ -157,18 +156,7 @@ static struct platform_driver platform_lcd_driver = {
        .resume         = platform_lcd_resume,
 };
 
-static int __init platform_lcd_init(void)
-{
-       return platform_driver_register(&platform_lcd_driver);
-}
-
-static void __exit platform_lcd_cleanup(void)
-{
-       platform_driver_unregister(&platform_lcd_driver);
-}
-
-module_init(platform_lcd_init);
-module_exit(platform_lcd_cleanup);
+module_platform_driver(platform_lcd_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
 MODULE_LICENSE("GPL v2");
index 8b5b2a4..7496d04 100644 (file)
@@ -169,10 +169,9 @@ static int pwm_backlight_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int pwm_backlight_suspend(struct platform_device *pdev,
-                                pm_message_t state)
+static int pwm_backlight_suspend(struct device *dev)
 {
-       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct backlight_device *bl = dev_get_drvdata(dev);
        struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
 
        if (pb->notify)
@@ -184,40 +183,32 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
        return 0;
 }
 
-static int pwm_backlight_resume(struct platform_device *pdev)
+static int pwm_backlight_resume(struct device *dev)
 {
-       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct backlight_device *bl = dev_get_drvdata(dev);
 
        backlight_update_status(bl);
        return 0;
 }
-#else
-#define pwm_backlight_suspend  NULL
-#define pwm_backlight_resume   NULL
+
+static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend,
+                        pwm_backlight_resume);
+
 #endif
 
 static struct platform_driver pwm_backlight_driver = {
        .driver         = {
                .name   = "pwm-backlight",
                .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &pwm_backlight_pm_ops,
+#endif
        },
        .probe          = pwm_backlight_probe,
        .remove         = pwm_backlight_remove,
-       .suspend        = pwm_backlight_suspend,
-       .resume         = pwm_backlight_resume,
 };
 
-static int __init pwm_backlight_init(void)
-{
-       return platform_driver_register(&pwm_backlight_driver);
-}
-module_init(pwm_backlight_init);
-
-static void __exit pwm_backlight_exit(void)
-{
-       platform_driver_unregister(&pwm_backlight_driver);
-}
-module_exit(pwm_backlight_exit);
+module_platform_driver(pwm_backlight_driver);
 
 MODULE_DESCRIPTION("PWM based Backlight Driver");
 MODULE_LICENSE("GPL");
index fbe9e93..4e915f5 100644 (file)
@@ -236,17 +236,7 @@ static struct platform_driver wm831x_backlight_driver = {
        .remove         = wm831x_backlight_remove,
 };
 
-static int __init wm831x_backlight_init(void)
-{
-       return platform_driver_register(&wm831x_backlight_driver);
-}
-module_init(wm831x_backlight_init);
-
-static void __exit wm831x_backlight_exit(void)
-{
-       platform_driver_unregister(&wm831x_backlight_driver);
-}
-module_exit(wm831x_backlight_exit);
+module_platform_driver(wm831x_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com");
index 79e2ca7..e95d1b6 100644 (file)
@@ -27,6 +27,9 @@ config COMPAT_BINFMT_ELF
        bool
        depends on COMPAT && BINFMT_ELF
 
+config ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       bool
+
 config BINFMT_ELF_FDPIC
        bool "Kernel support for FDPIC ELF binaries"
        default y
index 21ac5ee..bcb884e 100644 (file)
@@ -794,7 +794,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         * default mmap base, as well as whatever program they
                         * might try to exec.  This is because the brk will
                         * follow the loader, and is not movable.  */
-#if defined(CONFIG_X86) || defined(CONFIG_ARM)
+#ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE
                        /* Memory randomization might have been switched off
                         * in runtime via sysctl.
                         * If that is the case, retain the original non-zero
index 97fbe93..20375e6 100644 (file)
@@ -1081,7 +1081,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
 again:
        for (i = 0; i < num_pages; i++) {
                pages[i] = find_or_create_page(inode->i_mapping, index + i,
-                                              mask);
+                                              mask | __GFP_WRITE);
                if (!pages[i]) {
                        faili = i - 1;
                        err = -ENOMEM;
index 3f64b9f..aeb135c 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -59,6 +59,8 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
+
+#include <trace/events/task.h>
 #include "internal.h"
 
 int core_uses_pid;
@@ -1054,6 +1056,8 @@ void set_task_comm(struct task_struct *tsk, char *buf)
 {
        task_lock(tsk);
 
+       trace_task_rename(tsk, buf);
+
        /*
         * Threads may access current->comm without holding
         * the task lock, so write the string carefully.
index 8753575..4fa4f09 100644 (file)
@@ -776,6 +776,8 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan)
        else
                __count_vm_events(PGINODESTEAL, reap);
        spin_unlock(&sb->s_inode_lru_lock);
+       if (current->reclaim_state)
+               current->reclaim_state->reclaimed_slab += reap;
 
        dispose_list(&freeable);
 }
index a1dddda..8173dfd 100644 (file)
 #include <linux/pid_namespace.h>
 #include <linux/fs_struct.h>
 #include <linux/slab.h>
+#include <linux/flex_array.h>
 #ifdef CONFIG_HARDWALL
 #include <asm/hardwall.h>
 #endif
+#include <trace/events/oom.h>
 #include "internal.h"
 
 /* NOTE:
@@ -133,6 +135,8 @@ struct pid_entry {
                NULL, &proc_single_file_operations,     \
                { .proc_show = show } )
 
+static int proc_fd_permission(struct inode *inode, int mask);
+
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
  * and .. links.
@@ -165,9 +169,9 @@ static int get_task_root(struct task_struct *task, struct path *root)
        return result;
 }
 
-static int proc_cwd_link(struct inode *inode, struct path *path)
+static int proc_cwd_link(struct dentry *dentry, struct path *path)
 {
-       struct task_struct *task = get_proc_task(inode);
+       struct task_struct *task = get_proc_task(dentry->d_inode);
        int result = -ENOENT;
 
        if (task) {
@@ -182,9 +186,9 @@ static int proc_cwd_link(struct inode *inode, struct path *path)
        return result;
 }
 
-static int proc_root_link(struct inode *inode, struct path *path)
+static int proc_root_link(struct dentry *dentry, struct path *path)
 {
-       struct task_struct *task = get_proc_task(inode);
+       struct task_struct *task = get_proc_task(dentry->d_inode);
        int result = -ENOENT;
 
        if (task) {
@@ -627,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
        return 0;
 }
 
+/*
+ * May current process learn task's sched/cmdline info (for hide_pid_min=1)
+ * or euid/egid (for hide_pid_min=2)?
+ */
+static bool has_pid_permissions(struct pid_namespace *pid,
+                                struct task_struct *task,
+                                int hide_pid_min)
+{
+       if (pid->hide_pid < hide_pid_min)
+               return true;
+       if (in_group_p(pid->pid_gid))
+               return true;
+       return ptrace_may_access(task, PTRACE_MODE_READ);
+}
+
+
+static int proc_pid_permission(struct inode *inode, int mask)
+{
+       struct pid_namespace *pid = inode->i_sb->s_fs_info;
+       struct task_struct *task;
+       bool has_perms;
+
+       task = get_proc_task(inode);
+       has_perms = has_pid_permissions(pid, task, 1);
+       put_task_struct(task);
+
+       if (!has_perms) {
+               if (pid->hide_pid == 2) {
+                       /*
+                        * Let's make getdents(), stat(), and open()
+                        * consistent with each other.  If a process
+                        * may not stat() a file, it shouldn't be seen
+                        * in procfs at all.
+                        */
+                       return -ENOENT;
+               }
+
+               return -EPERM;
+       }
+       return generic_permission(inode, mask);
+}
+
+
+
 static const struct inode_operations proc_def_inode_operations = {
        .setattr        = proc_setattr,
 };
@@ -1010,6 +1058,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        else
                task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) /
                                                                -OOM_DISABLE;
+       trace_oom_score_adj_update(task);
 err_sighand:
        unlock_task_sighand(task, &flags);
 err_task_lock:
@@ -1097,6 +1146,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
        task->signal->oom_score_adj = oom_score_adj;
        if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
                task->signal->oom_score_adj_min = oom_score_adj;
+       trace_oom_score_adj_update(task);
        /*
         * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is
         * always attainable.
@@ -1453,13 +1503,13 @@ static const struct file_operations proc_pid_set_comm_operations = {
        .release        = single_release,
 };
 
-static int proc_exe_link(struct inode *inode, struct path *exe_path)
+static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 {
        struct task_struct *task;
        struct mm_struct *mm;
        struct file *exe_file;
 
-       task = get_proc_task(inode);
+       task = get_proc_task(dentry->d_inode);
        if (!task)
                return -ENOENT;
        mm = get_task_mm(task);
@@ -1489,7 +1539,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
        if (!proc_fd_access_allowed(inode))
                goto out;
 
-       error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
+       error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path);
 out:
        return ERR_PTR(error);
 }
@@ -1528,7 +1578,7 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
        if (!proc_fd_access_allowed(inode))
                goto out;
 
-       error = PROC_I(inode)->op.proc_get_link(inode, &path);
+       error = PROC_I(inode)->op.proc_get_link(dentry, &path);
        if (error)
                goto out;
 
@@ -1609,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
        struct inode *inode = dentry->d_inode;
        struct task_struct *task;
        const struct cred *cred;
+       struct pid_namespace *pid = dentry->d_sb->s_fs_info;
 
        generic_fillattr(inode, stat);
 
@@ -1617,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
        stat->gid = 0;
        task = pid_task(proc_pid(inode), PIDTYPE_PID);
        if (task) {
+               if (!has_pid_permissions(pid, task, 2)) {
+                       rcu_read_unlock();
+                       /*
+                        * This doesn't prevent learning whether PID exists,
+                        * it only makes getattr() consistent with readdir().
+                        */
+                       return -ENOENT;
+               }
                if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
                    task_dumpable(task)) {
                        cred = __task_cred(task);
@@ -1820,9 +1879,9 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
        return -ENOENT;
 }
 
-static int proc_fd_link(struct inode *inode, struct path *path)
+static int proc_fd_link(struct dentry *dentry, struct path *path)
 {
-       return proc_fd_info(inode, path, NULL);
+       return proc_fd_info(dentry->d_inode, path, NULL);
 }
 
 static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
@@ -2043,6 +2102,355 @@ static const struct file_operations proc_fd_operations = {
        .llseek         = default_llseek,
 };
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
+
+/*
+ * dname_to_vma_addr - maps a dentry name into two unsigned longs
+ * which represent vma start and end addresses.
+ */
+static int dname_to_vma_addr(struct dentry *dentry,
+                            unsigned long *start, unsigned long *end)
+{
+       if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+       unsigned long vm_start, vm_end;
+       bool exact_vma_exists = false;
+       struct mm_struct *mm = NULL;
+       struct task_struct *task;
+       const struct cred *cred;
+       struct inode *inode;
+       int status = 0;
+
+       if (nd && nd->flags & LOOKUP_RCU)
+               return -ECHILD;
+
+       if (!capable(CAP_SYS_ADMIN)) {
+               status = -EACCES;
+               goto out_notask;
+       }
+
+       inode = dentry->d_inode;
+       task = get_proc_task(inode);
+       if (!task)
+               goto out_notask;
+
+       if (!ptrace_may_access(task, PTRACE_MODE_READ))
+               goto out;
+
+       mm = get_task_mm(task);
+       if (!mm)
+               goto out;
+
+       if (!dname_to_vma_addr(dentry, &vm_start, &vm_end)) {
+               down_read(&mm->mmap_sem);
+               exact_vma_exists = !!find_exact_vma(mm, vm_start, vm_end);
+               up_read(&mm->mmap_sem);
+       }
+
+       mmput(mm);
+
+       if (exact_vma_exists) {
+               if (task_dumpable(task)) {
+                       rcu_read_lock();
+                       cred = __task_cred(task);
+                       inode->i_uid = cred->euid;
+                       inode->i_gid = cred->egid;
+                       rcu_read_unlock();
+               } else {
+                       inode->i_uid = 0;
+                       inode->i_gid = 0;
+               }
+               security_task_to_inode(task, inode);
+               status = 1;
+       }
+
+out:
+       put_task_struct(task);
+
+out_notask:
+       if (status <= 0)
+               d_drop(dentry);
+
+       return status;
+}
+
+static const struct dentry_operations tid_map_files_dentry_operations = {
+       .d_revalidate   = map_files_d_revalidate,
+       .d_delete       = pid_delete_dentry,
+};
+
+static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
+{
+       unsigned long vm_start, vm_end;
+       struct vm_area_struct *vma;
+       struct task_struct *task;
+       struct mm_struct *mm;
+       int rc;
+
+       rc = -ENOENT;
+       task = get_proc_task(dentry->d_inode);
+       if (!task)
+               goto out;
+
+       mm = get_task_mm(task);
+       put_task_struct(task);
+       if (!mm)
+               goto out;
+
+       rc = dname_to_vma_addr(dentry, &vm_start, &vm_end);
+       if (rc)
+               goto out_mmput;
+
+       down_read(&mm->mmap_sem);
+       vma = find_exact_vma(mm, vm_start, vm_end);
+       if (vma && vma->vm_file) {
+               *path = vma->vm_file->f_path;
+               path_get(path);
+               rc = 0;
+       }
+       up_read(&mm->mmap_sem);
+
+out_mmput:
+       mmput(mm);
+out:
+       return rc;
+}
+
+struct map_files_info {
+       struct file     *file;
+       unsigned long   len;
+       unsigned char   name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
+};
+
+static struct dentry *
+proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
+                          struct task_struct *task, const void *ptr)
+{
+       const struct file *file = ptr;
+       struct proc_inode *ei;
+       struct inode *inode;
+
+       if (!file)
+               return ERR_PTR(-ENOENT);
+
+       inode = proc_pid_make_inode(dir->i_sb, task);
+       if (!inode)
+               return ERR_PTR(-ENOENT);
+
+       ei = PROC_I(inode);
+       ei->op.proc_get_link = proc_map_files_get_link;
+
+       inode->i_op = &proc_pid_link_inode_operations;
+       inode->i_size = 64;
+       inode->i_mode = S_IFLNK;
+
+       if (file->f_mode & FMODE_READ)
+               inode->i_mode |= S_IRUSR;
+       if (file->f_mode & FMODE_WRITE)
+               inode->i_mode |= S_IWUSR;
+
+       d_set_d_op(dentry, &tid_map_files_dentry_operations);
+       d_add(dentry, inode);
+
+       return NULL;
+}
+
+static struct dentry *proc_map_files_lookup(struct inode *dir,
+               struct dentry *dentry, struct nameidata *nd)
+{
+       unsigned long vm_start, vm_end;
+       struct vm_area_struct *vma;
+       struct task_struct *task;
+       struct dentry *result;
+       struct mm_struct *mm;
+
+       result = ERR_PTR(-EACCES);
+       if (!capable(CAP_SYS_ADMIN))
+               goto out;
+
+       result = ERR_PTR(-ENOENT);
+       task = get_proc_task(dir);
+       if (!task)
+               goto out;
+
+       result = ERR_PTR(-EACCES);
+       if (lock_trace(task))
+               goto out_put_task;
+
+       result = ERR_PTR(-ENOENT);
+       if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
+               goto out_unlock;
+
+       mm = get_task_mm(task);
+       if (!mm)
+               goto out_unlock;
+
+       down_read(&mm->mmap_sem);
+       vma = find_exact_vma(mm, vm_start, vm_end);
+       if (!vma)
+               goto out_no_vma;
+
+       result = proc_map_files_instantiate(dir, dentry, task, vma->vm_file);
+
+out_no_vma:
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+out_unlock:
+       unlock_trace(task);
+out_put_task:
+       put_task_struct(task);
+out:
+       return result;
+}
+
+static const struct inode_operations proc_map_files_inode_operations = {
+       .lookup         = proc_map_files_lookup,
+       .permission     = proc_fd_permission,
+       .setattr        = proc_setattr,
+};
+
+static int
+proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct dentry *dentry = filp->f_path.dentry;
+       struct inode *inode = dentry->d_inode;
+       struct vm_area_struct *vma;
+       struct task_struct *task;
+       struct mm_struct *mm;
+       ino_t ino;
+       int ret;
+
+       ret = -EACCES;
+       if (!capable(CAP_SYS_ADMIN))
+               goto out;
+
+       ret = -ENOENT;
+       task = get_proc_task(inode);
+       if (!task)
+               goto out;
+
+       ret = -EACCES;
+       if (lock_trace(task))
+               goto out_put_task;
+
+       ret = 0;
+       switch (filp->f_pos) {
+       case 0:
+               ino = inode->i_ino;
+               if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0)
+                       goto out_unlock;
+               filp->f_pos++;
+       case 1:
+               ino = parent_ino(dentry);
+               if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
+                       goto out_unlock;
+               filp->f_pos++;
+       default:
+       {
+               unsigned long nr_files, pos, i;
+               struct flex_array *fa = NULL;
+               struct map_files_info info;
+               struct map_files_info *p;
+
+               mm = get_task_mm(task);
+               if (!mm)
+                       goto out_unlock;
+               down_read(&mm->mmap_sem);
+
+               nr_files = 0;
+
+               /*
+                * We need two passes here:
+                *
+                *  1) Collect vmas of mapped files with mmap_sem taken
+                *  2) Release mmap_sem and instantiate entries
+                *
+                * otherwise we get lockdep complained, since filldir()
+                * routine might require mmap_sem taken in might_fault().
+                */
+
+               for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) {
+                       if (vma->vm_file && ++pos > filp->f_pos)
+                               nr_files++;
+               }
+
+               if (nr_files) {
+                       fa = flex_array_alloc(sizeof(info), nr_files,
+                                               GFP_KERNEL);
+                       if (!fa || flex_array_prealloc(fa, 0, nr_files,
+                                                       GFP_KERNEL)) {
+                               ret = -ENOMEM;
+                               if (fa)
+                                       flex_array_free(fa);
+                               up_read(&mm->mmap_sem);
+                               mmput(mm);
+                               goto out_unlock;
+                       }
+                       for (i = 0, vma = mm->mmap, pos = 2; vma;
+                                       vma = vma->vm_next) {
+                               if (!vma->vm_file)
+                                       continue;
+                               if (++pos <= filp->f_pos)
+                                       continue;
+
+                               get_file(vma->vm_file);
+                               info.file = vma->vm_file;
+                               info.len = snprintf(info.name,
+                                               sizeof(info.name), "%lx-%lx",
+                                               vma->vm_start, vma->vm_end);
+                               if (flex_array_put(fa, i++, &info, GFP_KERNEL))
+                                       BUG();
+                       }
+               }
+               up_read(&mm->mmap_sem);
+
+               for (i = 0; i < nr_files; i++) {
+                       p = flex_array_get(fa, i);
+                       ret = proc_fill_cache(filp, dirent, filldir,
+                                             p->name, p->len,
+                                             proc_map_files_instantiate,
+                                             task, p->file);
+                       if (ret)
+                               break;
+                       filp->f_pos++;
+                       fput(p->file);
+               }
+               for (; i < nr_files; i++) {
+                       /*
+                        * In case of error don't forget
+                        * to put rest of file refs.
+                        */
+                       p = flex_array_get(fa, i);
+                       fput(p->file);
+               }
+               if (fa)
+                       flex_array_free(fa);
+               mmput(mm);
+       }
+       }
+
+out_unlock:
+       unlock_trace(task);
+out_put_task:
+       put_task_struct(task);
+out:
+       return ret;
+}
+
+static const struct file_operations proc_map_files_operations = {
+       .read           = generic_read_dir,
+       .readdir        = proc_map_files_readdir,
+       .llseek         = default_llseek,
+};
+
+#endif /* CONFIG_CHECKPOINT_RESTORE */
+
 /*
  * /proc/pid/fd needs a special permission handler so that a process can still
  * access /proc/self/fd after it has executed a setuid().
@@ -2658,6 +3066,9 @@ static const struct inode_operations proc_task_inode_operations;
 static const struct pid_entry tgid_base_stuff[] = {
        DIR("task",       S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
        DIR("fd",         S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       DIR("map_files",  S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations),
+#endif
        DIR("fdinfo",     S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
        DIR("ns",         S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
 #ifdef CONFIG_NET
@@ -2761,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
        .lookup         = proc_tgid_base_lookup,
        .getattr        = pid_getattr,
        .setattr        = proc_setattr,
+       .permission     = proc_pid_permission,
 };
 
 static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
@@ -2964,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
                                proc_pid_instantiate, iter.task, NULL);
 }
 
+static int fake_filldir(void *buf, const char *name, int namelen,
+                       loff_t offset, u64 ino, unsigned d_type)
+{
+       return 0;
+}
+
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
@@ -2971,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
        struct task_struct *reaper;
        struct tgid_iter iter;
        struct pid_namespace *ns;
+       filldir_t __filldir;
 
        if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
                goto out_no_task;
@@ -2992,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
        for (iter = next_tgid(ns, iter);
             iter.task;
             iter.tgid += 1, iter = next_tgid(ns, iter)) {
+               if (has_pid_permissions(ns, iter.task, 2))
+                       __filldir = filldir;
+               else
+                       __filldir = fake_filldir;
+
                filp->f_pos = iter.tgid + TGID_OFFSET;
-               if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
+               if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) {
                        put_task_struct(iter.task);
                        goto out;
                }
@@ -3328,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = {
        .lookup         = proc_task_lookup,
        .getattr        = proc_task_getattr,
        .setattr        = proc_setattr,
+       .permission     = proc_pid_permission,
 };
 
 static const struct file_operations proc_task_operations = {
index 51a1766..84fd323 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
+#include <linux/pid_namespace.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
@@ -17,7 +18,9 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sysctl.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/mount.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -101,12 +104,27 @@ void __init proc_init_inodecache(void)
                                             init_once);
 }
 
+static int proc_show_options(struct seq_file *seq, struct dentry *root)
+{
+       struct super_block *sb = root->d_sb;
+       struct pid_namespace *pid = sb->s_fs_info;
+
+       if (pid->pid_gid)
+               seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid);
+       if (pid->hide_pid != 0)
+               seq_printf(seq, ",hidepid=%u", pid->hide_pid);
+
+       return 0;
+}
+
 static const struct super_operations proc_sops = {
        .alloc_inode    = proc_alloc_inode,
        .destroy_inode  = proc_destroy_inode,
        .drop_inode     = generic_delete_inode,
        .evict_inode    = proc_evict_inode,
        .statfs         = simple_statfs,
+       .remount_fs     = proc_remount,
+       .show_options   = proc_show_options,
 };
 
 static void __pde_users_dec(struct proc_dir_entry *pde)
index 7838e5c..2925775 100644 (file)
@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde);
 
 int proc_fill_super(struct super_block *);
 struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
+int proc_remount(struct super_block *sb, int *flags, char *data);
 
 /*
  * These are generic /proc routines that use the internal
index 03102d9..46a15d8 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/bitops.h>
 #include <linux/mount.h>
 #include <linux/pid_namespace.h>
+#include <linux/parser.h>
 
 #include "internal.h"
 
@@ -36,6 +37,63 @@ static int proc_set_super(struct super_block *sb, void *data)
        return err;
 }
 
+enum {
+       Opt_gid, Opt_hidepid, Opt_err,
+};
+
+static const match_table_t tokens = {
+       {Opt_hidepid, "hidepid=%u"},
+       {Opt_gid, "gid=%u"},
+       {Opt_err, NULL},
+};
+
+static int proc_parse_options(char *options, struct pid_namespace *pid)
+{
+       char *p;
+       substring_t args[MAX_OPT_ARGS];
+       int option;
+
+       if (!options)
+               return 1;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               int token;
+               if (!*p)
+                       continue;
+
+               args[0].to = args[0].from = 0;
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_gid:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       pid->pid_gid = option;
+                       break;
+               case Opt_hidepid:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       if (option < 0 || option > 2) {
+                               pr_err("proc: hidepid value must be between 0 and 2.\n");
+                               return 0;
+                       }
+                       pid->hide_pid = option;
+                       break;
+               default:
+                       pr_err("proc: unrecognized mount option \"%s\" "
+                              "or missing value\n", p);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+int proc_remount(struct super_block *sb, int *flags, char *data)
+{
+       struct pid_namespace *pid = sb->s_fs_info;
+       return !proc_parse_options(data, pid);
+}
+
 static struct dentry *proc_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
@@ -43,11 +101,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        struct super_block *sb;
        struct pid_namespace *ns;
        struct proc_inode *ei;
+       char *options;
 
-       if (flags & MS_KERNMOUNT)
+       if (flags & MS_KERNMOUNT) {
                ns = (struct pid_namespace *)data;
-       else
+               options = NULL;
+       } else {
                ns = current->nsproxy->pid_ns;
+               options = data;
+       }
 
        sb = sget(fs_type, proc_test_super, proc_set_super, ns);
        if (IS_ERR(sb))
@@ -55,6 +117,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
 
        if (!sb->s_root) {
                sb->s_flags = flags;
+               if (!proc_parse_options(options, ns)) {
+                       deactivate_locked_super(sb);
+                       return ERR_PTR(-EINVAL);
+               }
                err = proc_fill_super(sb);
                if (err) {
                        deactivate_locked_super(sb);
index a945cd2..70de42f 100644 (file)
@@ -1364,10 +1364,7 @@ int reiserfs_init_bitmap_cache(struct super_block *sb)
        struct reiserfs_bitmap_info *bitmap;
        unsigned int bmap_nr = reiserfs_bmap_count(sb);
 
-       /* Avoid lock recursion in fault case */
-       reiserfs_write_unlock(sb);
        bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
-       reiserfs_write_lock(sb);
        if (bitmap == NULL)
                return -ENOMEM;
 
index eb71106..c3cf54f 100644 (file)
@@ -2678,16 +2678,10 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        char b[BDEVNAME_SIZE];
        int ret;
 
-       /*
-        * Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS
-        * dependency inversion warnings.
-        */
-       reiserfs_write_unlock(sb);
        journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal));
        if (!journal) {
                reiserfs_warning(sb, "journal-1256",
                                 "unable to get memory for journal structure");
-               reiserfs_write_lock(sb);
                return 1;
        }
        INIT_LIST_HEAD(&journal->j_bitmap_nodes);
@@ -2695,10 +2689,8 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        INIT_LIST_HEAD(&journal->j_working_list);
        INIT_LIST_HEAD(&journal->j_journal_list);
        journal->j_persistent_trans = 0;
-       ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
-                                          reiserfs_bmap_count(sb));
-       reiserfs_write_lock(sb);
-       if (ret)
+       if (reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
+                                          reiserfs_bmap_count(sb)))
                goto free_and_return;
 
        allocate_bitmap_nodes(sb);
@@ -2727,27 +2719,11 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
                goto free_and_return;
        }
 
-       /*
-        * We need to unlock here to avoid creating the following
-        * dependency:
-        * reiserfs_lock -> sysfs_mutex
-        * Because the reiserfs mmap path creates the following dependency:
-        * mm->mmap -> reiserfs_lock, hence we have
-        * mm->mmap -> reiserfs_lock ->sysfs_mutex
-        * This would ends up in a circular dependency with sysfs readdir path
-        * which does sysfs_mutex -> mm->mmap_sem
-        * This is fine because the reiserfs lock is useless in mount path,
-        * at least until we call journal_begin. We keep it for paranoid
-        * reasons.
-        */
-       reiserfs_write_unlock(sb);
        if (journal_init_dev(sb, journal, j_dev_name) != 0) {
-               reiserfs_write_lock(sb);
                reiserfs_warning(sb, "sh-462",
                                 "unable to initialize jornal device");
                goto free_and_return;
        }
-       reiserfs_write_lock(sb);
 
        rs = SB_DISK_SUPER_BLOCK(sb);
 
@@ -2829,9 +2805,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        journal->j_mount_id = 10;
        journal->j_state = 0;
        atomic_set(&(journal->j_jlock), 0);
-       reiserfs_write_unlock(sb);
        journal->j_cnode_free_list = allocate_cnodes(num_cnodes);
-       reiserfs_write_lock(sb);
        journal->j_cnode_free_orig = journal->j_cnode_free_list;
        journal->j_cnode_free = journal->j_cnode_free_list ? num_cnodes : 0;
        journal->j_cnode_used = 0;
@@ -2848,24 +2822,37 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
 
        init_journal_hash(sb);
        jl = journal->j_current_jl;
+
+       /*
+        * get_list_bitmap() may call flush_commit_list() which
+        * requires the lock. Calling flush_commit_list() shouldn't happen
+        * this early but I like to be paranoid.
+        */
+       reiserfs_write_lock(sb);
        jl->j_list_bitmap = get_list_bitmap(sb, jl);
+       reiserfs_write_unlock(sb);
        if (!jl->j_list_bitmap) {
                reiserfs_warning(sb, "journal-2005",
                                 "get_list_bitmap failed for journal list 0");
                goto free_and_return;
        }
-       if (journal_read(sb) < 0) {
+
+       /*
+        * Journal_read needs to be inspected in order to push down
+        * the lock further inside (or even remove it).
+        */
+       reiserfs_write_lock(sb);
+       ret = journal_read(sb);
+       reiserfs_write_unlock(sb);
+       if (ret < 0) {
                reiserfs_warning(sb, "reiserfs-2006",
                                 "Replay Failure, unable to mount");
                goto free_and_return;
        }
 
        reiserfs_mounted_fs_count++;
-       if (reiserfs_mounted_fs_count <= 1) {
-               reiserfs_write_unlock(sb);
+       if (reiserfs_mounted_fs_count <= 1)
                commit_wq = alloc_workqueue("reiserfs", WQ_MEM_RECLAIM, 0);
-               reiserfs_write_lock(sb);
-       }
 
        INIT_DELAYED_WORK(&journal->j_work, flush_async_commits);
        journal->j_work_sb = sb;
@@ -2896,14 +2883,13 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th,
            journal->j_cnode_free < (journal->j_trans_max * 3)) {
                return 1;
        }
-       /* protected by the BKL here */
+
        journal->j_len_alloc += new_alloc;
        th->t_blocks_allocated += new_alloc ;
        return 0;
 }
 
-/* this must be called inside a transaction, and requires the
-** kernel_lock to be held
+/* this must be called inside a transaction
 */
 void reiserfs_block_writes(struct reiserfs_transaction_handle *th)
 {
@@ -2914,8 +2900,7 @@ void reiserfs_block_writes(struct reiserfs_transaction_handle *th)
        return;
 }
 
-/* this must be called without a transaction started, and does not
-** require BKL
+/* this must be called without a transaction started
 */
 void reiserfs_allow_writes(struct super_block *s)
 {
@@ -2924,8 +2909,7 @@ void reiserfs_allow_writes(struct super_block *s)
        wake_up(&journal->j_join_wait);
 }
 
-/* this must be called without a transaction started, and does not
-** require BKL
+/* this must be called without a transaction started
 */
 void reiserfs_wait_on_write_block(struct super_block *s)
 {
index 1d42e70..e12d8b9 100644 (file)
@@ -1519,9 +1519,7 @@ static int read_super_block(struct super_block *s, int offset)
 static int reread_meta_blocks(struct super_block *s)
 {
        ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
-       reiserfs_write_unlock(s);
        wait_on_buffer(SB_BUFFER_WITH_SB(s));
-       reiserfs_write_lock(s);
        if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
                reiserfs_warning(s, "reiserfs-2504", "error reading the super");
                return 1;
@@ -1746,22 +1744,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        mutex_init(&REISERFS_SB(s)->lock);
        REISERFS_SB(s)->lock_depth = -1;
 
-       /*
-        * This function is called with the bkl, which also was the old
-        * locking used here.
-        * do_journal_begin() will soon check if we hold the lock (ie: was the
-        * bkl). This is likely because do_journal_begin() has several another
-        * callers because at this time, it doesn't seem to be necessary to
-        * protect against anything.
-        * Anyway, let's be conservative and lock for now.
-        */
-       reiserfs_write_lock(s);
-
        jdev_name = NULL;
        if (reiserfs_parse_options
            (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
             &commit_max_age, qf_names, &qfmt) == 0) {
-               goto error;
+               goto error_unlocked;
        }
        if (jdev_name && jdev_name[0]) {
                REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL);
@@ -1777,7 +1764,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        if (blocks) {
                SWARN(silent, s, "jmacd-7", "resize option for remount only");
-               goto error;
+               goto error_unlocked;
        }
 
        /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
@@ -1787,7 +1774,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
                SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
                      reiserfs_bdevname(s));
-               goto error;
+               goto error_unlocked;
        }
 
        rs = SB_DISK_SUPER_BLOCK(s);
@@ -1803,7 +1790,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                      "or increase size of your LVM partition");
                SWARN(silent, s, "", "Or may be you forgot to "
                      "reboot after fdisk when it told you to");
-               goto error;
+               goto error_unlocked;
        }
 
        sbi->s_mount_state = SB_REISERFS_STATE(s);
@@ -1811,8 +1798,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        if ((errval = reiserfs_init_bitmap_cache(s))) {
                SWARN(silent, s, "jmacd-8", "unable to read bitmap");
-               goto error;
+               goto error_unlocked;
        }
+
        errval = -EINVAL;
 #ifdef CONFIG_REISERFS_CHECK
        SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON");
@@ -1835,24 +1823,26 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (reiserfs_barrier_flush(s)) {
                printk("reiserfs: using flush barriers\n");
        }
+
        // set_device_ro(s->s_dev, 1) ;
        if (journal_init(s, jdev_name, old_format, commit_max_age)) {
                SWARN(silent, s, "sh-2022",
                      "unable to initialize journal space");
-               goto error;
+               goto error_unlocked;
        } else {
                jinit_done = 1; /* once this is set, journal_release must be called
                                 ** if we error out of the mount
                                 */
        }
+
        if (reread_meta_blocks(s)) {
                SWARN(silent, s, "jmacd-9",
                      "unable to reread meta blocks after journal init");
-               goto error;
+               goto error_unlocked;
        }
 
        if (replay_only(s))
-               goto error;
+               goto error_unlocked;
 
        if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) {
                SWARN(silent, s, "clm-7000",
@@ -1866,9 +1856,19 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                         reiserfs_init_locked_inode, (void *)(&args));
        if (!root_inode) {
                SWARN(silent, s, "jmacd-10", "get root inode failed");
-               goto error;
+               goto error_unlocked;
        }
 
+       /*
+        * This path assumed to be called with the BKL in the old times.
+        * Now we have inherited the big reiserfs lock from it and many
+        * reiserfs helpers called in the mount path and elsewhere require
+        * this lock to be held even if it's not always necessary. Let's be
+        * conservative and hold it early. The window can be reduced after
+        * careful review of the code.
+        */
+       reiserfs_write_lock(s);
+
        if (root_inode->i_state & I_NEW) {
                reiserfs_read_locked_inode(root_inode, &args);
                unlock_new_inode(root_inode);
@@ -1995,12 +1995,16 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        return (0);
 
 error:
-       if (jinit_done) {       /* kill the commit thread, free journal ram */
+       reiserfs_write_unlock(s);
+
+error_unlocked:
+       /* kill the commit thread, free journal ram */
+       if (jinit_done) {
+               reiserfs_write_lock(s);
                journal_release_error(NULL, s);
+               reiserfs_write_unlock(s);
        }
 
-       reiserfs_write_unlock(s);
-
        reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
index dfadc96..2f40791 100644 (file)
@@ -29,6 +29,7 @@
    the kernel context */
 #define __cold                 __attribute__((__cold__))
 
+#define __linktime_error(message) __attribute__((__error__(message)))
 
 #if __GNUC_MINOR__ >= 5
 /*
index 320d6c9..4a24354 100644 (file)
@@ -293,7 +293,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 #ifndef __compiletime_error
 # define __compiletime_error(message)
 #endif
-
+#ifndef __linktime_error
+# define __linktime_error(message)
+#endif
 /*
  * Prevent the compiler from merging or refetching accesses.  The compiler
  * is also forbidden from reordering successive instances of ACCESS_ONCE(),
index 3a76faf..581e74b 100644 (file)
@@ -36,6 +36,7 @@ struct vm_area_struct;
 #endif
 #define ___GFP_NO_KSWAPD       0x400000u
 #define ___GFP_OTHER_NODE      0x800000u
+#define ___GFP_WRITE           0x1000000u
 
 /*
  * GFP bitmasks..
@@ -85,6 +86,7 @@ struct vm_area_struct;
 
 #define __GFP_NO_KSWAPD        ((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
+#define __GFP_WRITE    ((__force gfp_t)___GFP_WRITE)   /* Allocator intends to dirty page */
 
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
@@ -92,7 +94,7 @@ struct vm_area_struct;
  */
 #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
 
-#define __GFP_BITS_SHIFT 24    /* Room for N __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 25    /* Room for N __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* This equals 0, but use constants in case they ever change */
@@ -313,7 +315,7 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
 static inline struct page *alloc_pages_exact_node(int nid, gfp_t gfp_mask,
                                                unsigned int order)
 {
-       VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES);
+       VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES || !node_online(nid));
 
        return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
 }
@@ -358,6 +360,7 @@ void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask);
 extern void __free_pages(struct page *page, unsigned int order);
 extern void free_pages(unsigned long addr, unsigned int order);
 extern void free_hot_cold_page(struct page *page, int cold);
+extern void free_hot_cold_page_list(struct list_head *list, int cold);
 
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr), 0)
@@ -367,9 +370,25 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp);
 void drain_all_pages(void);
 void drain_local_pages(void *dummy);
 
+/*
+ * gfp_allowed_mask is set to GFP_BOOT_MASK during early boot to restrict what
+ * GFP flags are used before interrupts are enabled. Once interrupts are
+ * enabled, it is set to __GFP_BITS_MASK while the system is running. During
+ * hibernation, it is used by PM to avoid I/O during memory allocation while
+ * devices are suspended.
+ */
 extern gfp_t gfp_allowed_mask;
 
 extern void pm_restrict_gfp_mask(void);
 extern void pm_restore_gfp_mask(void);
 
+#ifdef CONFIG_PM_SLEEP
+extern bool pm_suspended_storage(void);
+#else
+static inline bool pm_suspended_storage(void)
+{
+       return false;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 #endif /* __LINUX_GFP_H */
index e8b1597..f48e8a5 100644 (file)
@@ -665,6 +665,7 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 #define BUILD_BUG_ON_ZERO(e) (0)
 #define BUILD_BUG_ON_NULL(e) ((void*)0)
 #define BUILD_BUG_ON(condition)
+#define BUILD_BUG() (0)
 #else /* __CHECKER__ */
 
 /* Force a compilation error if a constant expression is not a power of 2 */
@@ -703,6 +704,21 @@ extern int __build_bug_on_failed;
                if (condition) __build_bug_on_failed = 1;       \
        } while(0)
 #endif
+
+/**
+ * BUILD_BUG - break compile if used.
+ *
+ * If you have some code that you expect the compiler to eliminate at
+ * build time, you should use BUILD_BUG to detect if it is
+ * unexpectedly used.
+ */
+#define BUILD_BUG()                                            \
+       do {                                                    \
+               extern void __build_bug_failed(void)            \
+                       __linktime_error("BUILD_BUG failed");   \
+               __build_bug_failed();                           \
+       } while (0)
+
 #endif /* __CHECKER__ */
 
 /* Trap pasters of __FUNCTION__ at compile-time */
diff --git a/include/linux/leds-tca6507.h b/include/linux/leds-tca6507.h
new file mode 100644 (file)
index 0000000..dcabf4f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * TCA6507 LED chip driver.
+ *
+ * Copyright (C) 2011 Neil Brown <neil@brown.name>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_TCA6507_H
+#define __LINUX_TCA6507_H
+#include <linux/leds.h>
+
+struct tca6507_platform_data {
+       struct led_platform_data leds;
+#ifdef CONFIG_GPIOLIB
+       int gpio_base;
+       void (*setup)(unsigned gpio_base, unsigned ngpio);
+#endif
+};
+
+#define        TCA6507_MAKE_GPIO 1
+#endif /* __LINUX_TCA6507_H*/
index 7978eec..7c727a9 100644 (file)
@@ -164,11 +164,11 @@ static inline void mpol_get(struct mempolicy *pol)
                atomic_inc(&pol->refcnt);
 }
 
-extern int __mpol_equal(struct mempolicy *a, struct mempolicy *b);
-static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b)
+extern bool __mpol_equal(struct mempolicy *a, struct mempolicy *b);
+static inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b)
 {
        if (a == b)
-               return 1;
+               return true;
        return __mpol_equal(a, b);
 }
 
@@ -257,9 +257,9 @@ static inline int vma_migratable(struct vm_area_struct *vma)
 
 struct mempolicy {};
 
-static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b)
+static inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b)
 {
-       return 1;
+       return true;
 }
 
 static inline void mpol_put(struct mempolicy *p)
index 5d9b4c9..6eba2cc 100644 (file)
@@ -1482,6 +1482,18 @@ static inline unsigned long vma_pages(struct vm_area_struct *vma)
        return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 }
 
+/* Look up the first VMA which exactly match the interval vm_start ... vm_end */
+static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm,
+                               unsigned long vm_start, unsigned long vm_end)
+{
+       struct vm_area_struct *vma = find_vma(mm, vm_start);
+
+       if (vma && (vma->vm_start != vm_start || vma->vm_end != vm_end))
+               vma = NULL;
+
+       return vma;
+}
+
 #ifdef CONFIG_MMU
 pgprot_t vm_get_page_prot(unsigned long vm_flags);
 #else
@@ -1618,5 +1630,22 @@ extern void copy_user_huge_page(struct page *dst, struct page *src,
                                unsigned int pages_per_huge_page);
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+extern unsigned int _debug_guardpage_minorder;
+
+static inline unsigned int debug_guardpage_minorder(void)
+{
+       return _debug_guardpage_minorder;
+}
+
+static inline bool page_is_guard(struct page *page)
+{
+       return test_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags);
+}
+#else
+static inline unsigned int debug_guardpage_minorder(void) { return 0; }
+static inline bool page_is_guard(struct page *page) { return false; }
+#endif /* CONFIG_DEBUG_PAGEALLOC */
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
index 3ac040f..ca6ca92 100644 (file)
@@ -317,6 +317,12 @@ struct zone {
         */
        unsigned long           lowmem_reserve[MAX_NR_ZONES];
 
+       /*
+        * This is a per-zone reserve of pages that should not be
+        * considered dirtyable memory.
+        */
+       unsigned long           dirty_balance_reserve;
+
 #ifdef CONFIG_NUMA
        int node;
        /*
index b0638fd..22691f6 100644 (file)
@@ -13,6 +13,7 @@
 
 enum page_debug_flags {
        PAGE_DEBUG_FLAG_POISON,         /* Page is poisoned */
+       PAGE_DEBUG_FLAG_GUARD,
 };
 
 /*
@@ -21,7 +22,8 @@ enum page_debug_flags {
  */
 
 #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
-#if !defined(CONFIG_PAGE_POISONING) \
+#if !defined(CONFIG_PAGE_POISONING) && \
+    !defined(CONFIG_PAGE_GUARD) \
 /* && !defined(CONFIG_PAGE_DEBUG_SOMETHING_ELSE) && ... */
 #error WANT_PAGE_DEBUG_FLAGS is turned on with no debug features!
 #endif
index bab82f4..ed17024 100644 (file)
@@ -21,7 +21,6 @@ struct pagevec {
 };
 
 void __pagevec_release(struct pagevec *pvec);
-void __pagevec_free(struct pagevec *pvec);
 void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru);
 void pagevec_strip(struct pagevec *pvec);
 unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
@@ -67,12 +66,6 @@ static inline void pagevec_release(struct pagevec *pvec)
                __pagevec_release(pvec);
 }
 
-static inline void pagevec_free(struct pagevec *pvec)
-{
-       if (pagevec_count(pvec))
-               __pagevec_free(pvec);
-}
-
 static inline void __pagevec_lru_add_anon(struct pagevec *pvec)
 {
        ____pagevec_lru_add(pvec, LRU_INACTIVE_ANON);
index 38d1032..e7cf666 100644 (file)
@@ -30,6 +30,8 @@ struct pid_namespace {
 #ifdef CONFIG_BSD_PROCESS_ACCT
        struct bsd_acct_struct *bacct;
 #endif
+       gid_t pid_gid;
+       int hide_pid;
 };
 
 extern struct pid_namespace init_pid_ns;
index 6d9e575..85c5073 100644 (file)
@@ -253,7 +253,7 @@ extern const struct proc_ns_operations utsns_operations;
 extern const struct proc_ns_operations ipcns_operations;
 
 union proc_op {
-       int (*proc_get_link)(struct inode *, struct path *);
+       int (*proc_get_link)(struct dentry *, struct path *);
        int (*proc_read)(struct task_struct *task, char *page);
        int (*proc_show)(struct seq_file *m,
                struct pid_namespace *ns, struct pid *pid,
index 2148b12..1afb995 100644 (file)
@@ -120,6 +120,7 @@ void anon_vma_init(void);   /* create anon_vma_cachep */
 int  anon_vma_prepare(struct vm_area_struct *);
 void unlink_anon_vmas(struct vm_area_struct *);
 int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
+void anon_vma_moveto_tail(struct vm_area_struct *);
 int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
 void __anon_vma_link(struct vm_area_struct *);
 
index a822300..7987ce7 100644 (file)
@@ -254,6 +254,7 @@ extern void set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
 
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
+extern void block_sigmask(struct k_sigaction *ka, int signr);
 extern void exit_signals(struct task_struct *tsk);
 
 extern struct kmem_cache *sighand_cachep;
index 1e22e12..06061a7 100644 (file)
@@ -207,6 +207,7 @@ struct swap_list_t {
 /* linux/mm/page_alloc.c */
 extern unsigned long totalram_pages;
 extern unsigned long totalreserve_pages;
+extern unsigned long dirty_balance_reserve;
 extern unsigned int nr_free_buffer_pages(void);
 extern unsigned int nr_free_pagecache_pages(void);
 
index 0d556de..eb8b9f1 100644 (file)
@@ -297,32 +297,50 @@ extern struct workqueue_struct *system_unbound_wq;
 extern struct workqueue_struct *system_freezable_wq;
 
 extern struct workqueue_struct *
-__alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
-                     struct lock_class_key *key, const char *lock_name);
+__alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
+       struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6);
 
+/**
+ * alloc_workqueue - allocate a workqueue
+ * @fmt: printf format for the name of the workqueue
+ * @flags: WQ_* flags
+ * @max_active: max in-flight work items, 0 for default
+ * @args: args for @fmt
+ *
+ * Allocate a workqueue with the specified parameters.  For detailed
+ * information on WQ_* flags, please refer to Documentation/workqueue.txt.
+ *
+ * The __lock_name macro dance is to guarantee that single lock_class_key
+ * doesn't end up with different namesm, which isn't allowed by lockdep.
+ *
+ * RETURNS:
+ * Pointer to the allocated workqueue on success, %NULL on failure.
+ */
 #ifdef CONFIG_LOCKDEP
-#define alloc_workqueue(name, flags, max_active)               \
+#define alloc_workqueue(fmt, flags, max_active, args...)       \
 ({                                                             \
        static struct lock_class_key __key;                     \
        const char *__lock_name;                                \
                                                                \
-       if (__builtin_constant_p(name))                         \
-               __lock_name = (name);                           \
+       if (__builtin_constant_p(fmt))                          \
+               __lock_name = (fmt);                            \
        else                                                    \
-               __lock_name = #name;                            \
+               __lock_name = #fmt;                             \
                                                                \
-       __alloc_workqueue_key((name), (flags), (max_active),    \
-                             &__key, __lock_name);             \
+       __alloc_workqueue_key((fmt), (flags), (max_active),     \
+                             &__key, __lock_name, ##args);     \
 })
 #else
-#define alloc_workqueue(name, flags, max_active)               \
-       __alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
+#define alloc_workqueue(fmt, flags, max_active, args...)       \
+       __alloc_workqueue_key((fmt), (flags), (max_active),     \
+                             NULL, NULL, ##args)
 #endif
 
 /**
  * alloc_ordered_workqueue - allocate an ordered workqueue
- * @name: name of the workqueue
+ * @fmt: printf format for the name of the workqueue
  * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful)
+ * @args: args for @fmt
  *
  * Allocate an ordered workqueue.  An ordered workqueue executes at
  * most one work item at any given time in the queued order.  They are
@@ -331,11 +349,8 @@ __alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
  * RETURNS:
  * Pointer to the allocated workqueue on success, %NULL on failure.
  */
-static inline struct workqueue_struct *
-alloc_ordered_workqueue(const char *name, unsigned int flags)
-{
-       return alloc_workqueue(name, WQ_UNBOUND | flags, 1);
-}
+#define alloc_ordered_workqueue(fmt, flags, args...)           \
+       alloc_workqueue(fmt, WQ_UNBOUND | (flags), 1, ##args)
 
 #define create_workqueue(name)                                 \
        alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
index a378c29..6dff473 100644 (file)
@@ -124,6 +124,7 @@ void laptop_mode_timer_fn(unsigned long data);
 static inline void laptop_sync_completion(void) { }
 #endif
 void throttle_vm_writeout(gfp_t gfp_mask);
+bool zone_dirty_ok(struct zone *zone);
 
 extern unsigned long global_dirty_limit;
 
@@ -138,8 +139,6 @@ extern int vm_highmem_is_dirtyable;
 extern int block_dump;
 extern int laptop_mode;
 
-extern unsigned long determine_dirtyable_memory(void);
-
 extern int dirty_background_ratio_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos);
index a9c87ad..5f889f1 100644 (file)
@@ -147,7 +147,7 @@ DEFINE_EVENT(kmem_free, kmem_cache_free,
        TP_ARGS(call_site, ptr)
 );
 
-TRACE_EVENT(mm_page_free_direct,
+TRACE_EVENT(mm_page_free,
 
        TP_PROTO(struct page *page, unsigned int order),
 
@@ -169,7 +169,7 @@ TRACE_EVENT(mm_page_free_direct,
                        __entry->order)
 );
 
-TRACE_EVENT(mm_pagevec_free,
+TRACE_EVENT(mm_page_free_batched,
 
        TP_PROTO(struct page *page, int cold),
 
diff --git a/include/trace/events/oom.h b/include/trace/events/oom.h
new file mode 100644 (file)
index 0000000..dd4ba3b
--- /dev/null
@@ -0,0 +1,33 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM oom
+
+#if !defined(_TRACE_OOM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_OOM_H
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(oom_score_adj_update,
+
+       TP_PROTO(struct task_struct *task),
+
+       TP_ARGS(task),
+
+       TP_STRUCT__entry(
+               __field(        pid_t,  pid)
+               __array(        char,   comm,   TASK_COMM_LEN )
+               __field(         int,   oom_score_adj)
+       ),
+
+       TP_fast_assign(
+               __entry->pid = task->pid;
+               memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
+               __entry->oom_score_adj = task->signal->oom_score_adj;
+       ),
+
+       TP_printk("pid=%d comm=%s oom_score_adj=%d",
+               __entry->pid, __entry->comm, __entry->oom_score_adj)
+);
+
+#endif
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/task.h b/include/trace/events/task.h
new file mode 100644 (file)
index 0000000..b53add0
--- /dev/null
@@ -0,0 +1,61 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM task
+
+#if !defined(_TRACE_TASK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_TASK_H
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(task_newtask,
+
+       TP_PROTO(struct task_struct *task, unsigned long clone_flags),
+
+       TP_ARGS(task, clone_flags),
+
+       TP_STRUCT__entry(
+               __field(        pid_t,  pid)
+               __array(        char,   comm, TASK_COMM_LEN)
+               __field( unsigned long, clone_flags)
+               __field(        int,    oom_score_adj)
+       ),
+
+       TP_fast_assign(
+               __entry->pid = task->pid;
+               memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
+               __entry->clone_flags = clone_flags;
+               __entry->oom_score_adj = task->signal->oom_score_adj;
+       ),
+
+       TP_printk("pid=%d comm=%s clone_flags=%lx oom_score_adj=%d",
+               __entry->pid, __entry->comm,
+               __entry->clone_flags, __entry->oom_score_adj)
+);
+
+TRACE_EVENT(task_rename,
+
+       TP_PROTO(struct task_struct *task, char *comm),
+
+       TP_ARGS(task, comm),
+
+       TP_STRUCT__entry(
+               __field(        pid_t,  pid)
+               __array(        char, oldcomm,  TASK_COMM_LEN)
+               __array(        char, newcomm,  TASK_COMM_LEN)
+               __field(        int, oom_score_adj)
+       ),
+
+       TP_fast_assign(
+               __entry->pid = task->pid;
+               memcpy(entry->oldcomm, task->comm, TASK_COMM_LEN);
+               memcpy(entry->newcomm, comm, TASK_COMM_LEN);
+               __entry->oom_score_adj = task->signal->oom_score_adj;
+       ),
+
+       TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%d",
+               __entry->pid, __entry->oldcomm,
+               __entry->newcomm, __entry->oom_score_adj)
+);
+
+#endif
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 9a142a2..9b7c8ab 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/nsproxy.h>
 #include <linux/pid.h>
 #include <linux/ipc_namespace.h>
+#include <linux/user_namespace.h>
 #include <linux/slab.h>
 
 #include <net/sock.h>
@@ -542,9 +543,13 @@ static void __do_notify(struct mqueue_inode_info *info)
                        sig_i.si_errno = 0;
                        sig_i.si_code = SI_MESGQ;
                        sig_i.si_value = info->notify.sigev_value;
+                       /* map current pid/uid into info->owner's namespaces */
+                       rcu_read_lock();
                        sig_i.si_pid = task_tgid_nr_ns(current,
                                                ns_of_pid(info->notify_owner));
-                       sig_i.si_uid = current_uid();
+                       sig_i.si_uid = user_ns_map_uid(info->user->user_ns,
+                                               current_cred(), current_uid());
+                       rcu_read_unlock();
 
                        kill_pid_info(info->notify.sigev_signo,
                                      &sig_i, info->notify_owner);
index b00711c..5e1391b 100644 (file)
@@ -76,6 +76,9 @@
 
 #include <trace/events/sched.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/task.h>
+
 /*
  * Protected counters by write_lock_irq(&tasklist_lock)
  */
@@ -1370,6 +1373,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if (clone_flags & CLONE_THREAD)
                threadgroup_change_end(current);
        perf_event_fork(p);
+
+       trace_task_newtask(p, clone_flags);
+
        return p;
 
 bad_fork_free_pid:
index cbe2c14..1cf8890 100644 (file)
@@ -858,6 +858,9 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
            PageReserved(page))
                return NULL;
 
+       if (page_is_guard(page))
+               return NULL;
+
        return page;
 }
 
@@ -920,6 +923,9 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn)
            && (!kernel_page_present(page) || pfn_is_nosave(pfn)))
                return NULL;
 
+       if (page_is_guard(page))
+               return NULL;
+
        return page;
 }
 
index bb0efa5..c73c428 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/freezer.h>
 #include <linux/pid_namespace.h>
 #include <linux/nsproxy.h>
+#include <linux/user_namespace.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
 
@@ -1019,6 +1020,34 @@ static inline int legacy_queue(struct sigpending *signals, int sig)
        return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
 }
 
+/*
+ * map the uid in struct cred into user namespace *ns
+ */
+static inline uid_t map_cred_ns(const struct cred *cred,
+                               struct user_namespace *ns)
+{
+       return user_ns_map_uid(ns, cred, cred->uid);
+}
+
+#ifdef CONFIG_USER_NS
+static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t)
+{
+       if (current_user_ns() == task_cred_xxx(t, user_ns))
+               return;
+
+       if (SI_FROMKERNEL(info))
+               return;
+
+       info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns),
+                                       current_cred(), info->si_uid);
+}
+#else
+static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t)
+{
+       return;
+}
+#endif
+
 static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        int group, int from_ancestor_ns)
 {
@@ -1088,6 +1117,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
                                q->info.si_pid = 0;
                        break;
                }
+
+               userns_fixup_signal_uid(&q->info, t);
+
        } else if (!is_si_special(info)) {
                if (sig >= SIGRTMIN && info->si_code != SI_USER) {
                        /*
@@ -1626,7 +1658,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
         */
        rcu_read_lock();
        info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
-       info.si_uid = __task_cred(tsk)->uid;
+       info.si_uid = map_cred_ns(__task_cred(tsk),
+                       task_cred_xxx(tsk->parent, user_ns));
        rcu_read_unlock();
 
        info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime);
@@ -1709,7 +1742,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
         */
        rcu_read_lock();
        info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns);
-       info.si_uid = __task_cred(tsk)->uid;
+       info.si_uid = map_cred_ns(__task_cred(tsk),
+                       task_cred_xxx(parent, user_ns));
        rcu_read_unlock();
 
        info.si_utime = cputime_to_clock_t(tsk->utime);
@@ -2125,8 +2159,11 @@ static int ptrace_signal(int signr, siginfo_t *info,
                info->si_signo = signr;
                info->si_errno = 0;
                info->si_code = SI_USER;
+               rcu_read_lock();
                info->si_pid = task_pid_vnr(current->parent);
-               info->si_uid = task_uid(current->parent);
+               info->si_uid = map_cred_ns(__task_cred(current->parent),
+                               current_user_ns());
+               rcu_read_unlock();
        }
 
        /* If the (new) signal is now blocked, requeue it.  */
@@ -2318,6 +2355,27 @@ relock:
        return signr;
 }
 
+/**
+ * block_sigmask - add @ka's signal mask to current->blocked
+ * @ka: action for @signr
+ * @signr: signal that has been successfully delivered
+ *
+ * This function should be called when a signal has succesfully been
+ * delivered. It adds the mask of signals for @ka to current->blocked
+ * so that they are blocked during the execution of the signal
+ * handler. In addition, @signr will be blocked unless %SA_NODEFER is
+ * set in @ka->sa.sa_flags.
+ */
+void block_sigmask(struct k_sigaction *ka, int signr)
+{
+       sigset_t blocked;
+
+       sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
+               sigaddset(&blocked, signr);
+       set_current_blocked(&blocked);
+}
+
 /*
  * It could be that complete_signal() picked us to notify about the
  * group-wide signal. Other threads should be notified now to take
index 42fa9ad..bec7b5b 100644 (file)
@@ -242,10 +242,10 @@ struct workqueue_struct {
 
        int                     nr_drainers;    /* W: drain in progress */
        int                     saved_max_active; /* W: saved cwq max_active */
-       const char              *name;          /* I: workqueue name */
 #ifdef CONFIG_LOCKDEP
        struct lockdep_map      lockdep_map;
 #endif
+       char                    name[];         /* I: workqueue name */
 };
 
 struct workqueue_struct *system_wq __read_mostly;
@@ -2954,14 +2954,29 @@ static int wq_clamp_max_active(int max_active, unsigned int flags,
        return clamp_val(max_active, 1, lim);
 }
 
-struct workqueue_struct *__alloc_workqueue_key(const char *name,
+struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
                                               unsigned int flags,
                                               int max_active,
                                               struct lock_class_key *key,
-                                              const char *lock_name)
+                                              const char *lock_name, ...)
 {
+       va_list args, args1;
        struct workqueue_struct *wq;
        unsigned int cpu;
+       size_t namelen;
+
+       /* determine namelen, allocate wq and format name */
+       va_start(args, lock_name);
+       va_copy(args1, args);
+       namelen = vsnprintf(NULL, 0, fmt, args) + 1;
+
+       wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
+       if (!wq)
+               goto err;
+
+       vsnprintf(wq->name, namelen, fmt, args1);
+       va_end(args);
+       va_end(args1);
 
        /*
         * Workqueues which may be used during memory reclaim should
@@ -2978,12 +2993,9 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
                flags |= WQ_HIGHPRI;
 
        max_active = max_active ?: WQ_DFL_ACTIVE;
-       max_active = wq_clamp_max_active(max_active, flags, name);
-
-       wq = kzalloc(sizeof(*wq), GFP_KERNEL);
-       if (!wq)
-               goto err;
+       max_active = wq_clamp_max_active(max_active, flags, wq->name);
 
+       /* init wq */
        wq->flags = flags;
        wq->saved_max_active = max_active;
        mutex_init(&wq->flush_mutex);
@@ -2991,7 +3003,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
        INIT_LIST_HEAD(&wq->flusher_queue);
        INIT_LIST_HEAD(&wq->flusher_overflow);
 
-       wq->name = name;
        lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
        INIT_LIST_HEAD(&wq->list);
 
@@ -3020,7 +3031,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
                if (!rescuer)
                        goto err;
 
-               rescuer->task = kthread_create(rescuer_thread, wq, "%s", name);
+               rescuer->task = kthread_create(rescuer_thread, wq, "%s",
+                                              wq->name);
                if (IS_ERR(rescuer->task))
                        goto err;
 
index 2a34392..e5ec1e9 100644 (file)
@@ -357,6 +357,7 @@ miss:
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(btree_get_prev);
 
 static int getpos(struct btree_geo *geo, unsigned long *node,
                unsigned long *key)
index a6e633a..4b35d2b 100644 (file)
@@ -51,20 +51,21 @@ static inline u32
 crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
 {
 # ifdef __LITTLE_ENDIAN
-#  define DO_CRC(x) crc = tab[0][(crc ^ (x)) & 255] ^ (crc >> 8)
-#  define DO_CRC4 crc = tab[3][(crc) & 255] ^ \
-               tab[2][(crc >> 8) & 255] ^ \
-               tab[1][(crc >> 16) & 255] ^ \
-               tab[0][(crc >> 24) & 255]
+#  define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8)
+#  define DO_CRC4 crc = t3[(crc) & 255] ^ \
+               t2[(crc >> 8) & 255] ^ \
+               t1[(crc >> 16) & 255] ^ \
+               t0[(crc >> 24) & 255]
 # else
-#  define DO_CRC(x) crc = tab[0][((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
-#  define DO_CRC4 crc = tab[0][(crc) & 255] ^ \
-               tab[1][(crc >> 8) & 255] ^ \
-               tab[2][(crc >> 16) & 255] ^ \
-               tab[3][(crc >> 24) & 255]
+#  define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
+#  define DO_CRC4 crc = t0[(crc) & 255] ^ \
+               t1[(crc >> 8) & 255] ^  \
+               t2[(crc >> 16) & 255] ^ \
+               t3[(crc >> 24) & 255]
 # endif
        const u32 *b;
        size_t    rem_len;
+       const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3];
 
        /* Align it */
        if (unlikely((long)buf & 3 && len)) {
index 8b1a477..4b24432 100644 (file)
@@ -4,6 +4,7 @@ config DEBUG_PAGEALLOC
        depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC
        depends on !KMEMCHECK
        select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC
+       select PAGE_GUARD if ARCH_SUPPORTS_DEBUG_PAGEALLOC
        ---help---
          Unmap pages from the kernel linear mapping after free_pages().
          This results in a large slowdown, but helps to find certain types
@@ -22,3 +23,7 @@ config WANT_PAGE_DEBUG_FLAGS
 config PAGE_POISONING
        bool
        select WANT_PAGE_DEBUG_FLAGS
+
+config PAGE_GUARD
+       bool
+       select WANT_PAGE_DEBUG_FLAGS
index 1a77012..668e94d 100644 (file)
@@ -56,7 +56,7 @@ early_param("bootmem_debug", bootmem_debug_setup);
 
 static unsigned long __init bootmap_bytes(unsigned long pages)
 {
-       unsigned long bytes = (pages + 7) / 8;
+       unsigned long bytes = DIV_ROUND_UP(pages, 8);
 
        return ALIGN(bytes, sizeof(long));
 }
@@ -171,7 +171,6 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
 
 static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 {
-       int aligned;
        struct page *page;
        unsigned long start, end, pages, count = 0;
 
@@ -181,14 +180,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        start = bdata->node_min_pfn;
        end = bdata->node_low_pfn;
 
-       /*
-        * If the start is aligned to the machines wordsize, we might
-        * be able to free pages in bulks of that order.
-        */
-       aligned = !(start & (BITS_PER_LONG - 1));
-
-       bdebug("nid=%td start=%lx end=%lx aligned=%d\n",
-               bdata - bootmem_node_data, start, end, aligned);
+       bdebug("nid=%td start=%lx end=%lx\n",
+               bdata - bootmem_node_data, start, end);
 
        while (start < end) {
                unsigned long *map, idx, vec;
@@ -196,12 +189,17 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                map = bdata->node_bootmem_map;
                idx = start - bdata->node_min_pfn;
                vec = ~map[idx / BITS_PER_LONG];
-
-               if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) {
+               /*
+                * If we have a properly aligned and fully unreserved
+                * BITS_PER_LONG block of pages in front of us, free
+                * it in one go.
+                */
+               if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) {
                        int order = ilog2(BITS_PER_LONG);
 
                        __free_pages_bootmem(pfn_to_page(start), order);
                        count += BITS_PER_LONG;
+                       start += BITS_PER_LONG;
                } else {
                        unsigned long off = 0;
 
@@ -214,8 +212,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                                vec >>= 1;
                                off++;
                        }
+                       start = ALIGN(start + 1, BITS_PER_LONG);
                }
-               start += BITS_PER_LONG;
        }
 
        page = virt_to_page(bdata->node_bootmem_map);