Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 16 Jun 2011 16:44:20 +0000 (09:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 16 Jun 2011 16:44:20 +0000 (09:44 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
  SELinux: skip file_name_trans_write() when policy downgraded.
  selinux: fix case of names with whitespace/multibytes on /selinux/create

91 files changed:
Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 [new file with mode: 0644]
Documentation/accounting/cgroupstats.txt
Documentation/cgroups/blkio-controller.txt
Documentation/cgroups/cgroups.txt
Documentation/cgroups/cpuacct.txt
Documentation/cgroups/cpusets.txt
Documentation/cgroups/devices.txt
Documentation/cgroups/freezer-subsystem.txt
Documentation/cgroups/memory.txt
Documentation/feature-removal-schedule.txt
Documentation/kmemleak.txt
Documentation/printk-formats.txt
Documentation/scheduler/sched-design-CFS.txt
Documentation/scheduler/sched-rt-group.txt
Documentation/vm/hwpoison.txt
MAINTAINERS
arch/alpha/kernel/osf_sys.c
arch/arm/boot/compressed/head.S
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/netx_defconfig
arch/arm/configs/viper_defconfig
arch/arm/configs/xcep_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/kernel/devtree.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/traps.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/devices.c
arch/arm/mach-davinci/gpio.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/include/mach/debug-macro.S
arch/arm/mach-mxs/ocotp.c
arch/arm/mach-u300/clock.h
arch/arm/mach-u300/include/mach/u300-regs.h
arch/arm/mach-u300/timer.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mm/context.c
arch/arm/mm/init.c
arch/arm/mm/proc-arm7tdmi.S
arch/arm/mm/proc-arm9tdmi.S
arch/arm/mm/proc-v7.S
arch/arm/plat-mxc/devices/platform-imx-dma.c
arch/avr32/configs/atngw100_mrmt_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/mips/configs/mtx1_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/ps3_defconfig
arch/sh/configs/titan_defconfig
drivers/char/hpet.c
drivers/leds/Kconfig
drivers/misc/apds990x.c
drivers/misc/cs5535-mfgpt.c
drivers/misc/spear13xx_pcie_gadget.c
drivers/mmc/host/mmci.c
drivers/staging/iio/accel/adis16201.h
drivers/staging/iio/accel/adis16203.h
drivers/tty/serial/pch_uart.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/adp8870_bl.c [new file with mode: 0644]
drivers/w1/masters/Kconfig
include/asm-generic/pgtable.h
include/linux/i2c/adp8870.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/kmsg_dump.h
include/linux/memcontrol.h
include/linux/swap.h
include/linux/topology.h
include/linux/uts.h
include/trace/events/vmscan.h
init/Kconfig
init/calibrate.c
kernel/exit.c
kernel/gcov/Kconfig
kernel/sched_rt.c
kernel/signal.c
lib/bitmap.c
mm/compaction.c
mm/huge_memory.c
mm/hugetlb.c
mm/ksm.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mmap.c
mm/page_cgroup.c
mm/thrash.c
mm/vmscan.c
scripts/checkpatch.pl

diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
new file mode 100644 (file)
index 0000000..aa11dbd
--- /dev/null
@@ -0,0 +1,56 @@
+What:          /sys/class/backlight/<backlight>/<ambient light zone>_max
+What:          /sys/class/backlight/<backlight>/l1_daylight_max
+What:          /sys/class/backlight/<backlight>/l2_bright_max
+What:          /sys/class/backlight/<backlight>/l3_office_max
+What:          /sys/class/backlight/<backlight>/l4_indoor_max
+What:          /sys/class/backlight/<backlight>/l5_dark_max
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Control the maximum brightness for <ambient light zone>
+               on this <backlight>. Values are between 0 and 127. This file
+               will also show the brightness level stored for this
+               <ambient light zone>.
+
+What:          /sys/class/backlight/<backlight>/<ambient light zone>_dim
+What:          /sys/class/backlight/<backlight>/l2_bright_dim
+What:          /sys/class/backlight/<backlight>/l3_office_dim
+What:          /sys/class/backlight/<backlight>/l4_indoor_dim
+What:          /sys/class/backlight/<backlight>/l5_dark_dim
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Control the dim brightness for <ambient light zone>
+               on this <backlight>. Values are between 0 and 127, typically
+               set to 0. Full off when the backlight is disabled.
+               This file will also show the dim brightness level stored for
+               this <ambient light zone>.
+
+What:          /sys/class/backlight/<backlight>/ambient_light_level
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Get conversion value of the light sensor.
+               This value is updated every 80 ms (when the light sensor
+               is enabled). Returns integer between 0 (dark) and
+               8000 (max ambient brightness)
+
+What:          /sys/class/backlight/<backlight>/ambient_light_zone
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Get/Set current ambient light zone. Reading returns
+               integer between 1..5 (1 = daylight, 2 = bright, ..., 5 = dark).
+               Writing a value between 1..5 forces the backlight controller
+               to enter the corresponding ambient light zone.
+               Writing 0 returns to normal/automatic ambient light level
+               operation. The ambient light sensing feature on these devices
+               is an extension to the API documented in
+               Documentation/ABI/stable/sysfs-class-backlight.
+               It can be enabled by writing the value stored in
+               /sys/class/backlight/<backlight>/max_brightness to
+               /sys/class/backlight/<backlight>/brightness.
\ No newline at end of file
index eda40fd39cad9df7927e7409765007af38020219..d16a9849e60e127c2cd234cd02dcc9d6f16d35ec 100644 (file)
@@ -21,7 +21,7 @@ information will not be available.
 To extract cgroup statistics a utility very similar to getdelays.c
 has been developed, the sample output of the utility is shown below
 
-~/balbir/cgroupstats # ./getdelays  -C "/cgroup/a"
+~/balbir/cgroupstats # ./getdelays  -C "/sys/fs/cgroup/a"
 sleeping 1, blocked 0, running 1, stopped 0, uninterruptible 0
-~/balbir/cgroupstats # ./getdelays  -C "/cgroup"
+~/balbir/cgroupstats # ./getdelays  -C "/sys/fs/cgroup"
 sleeping 155, blocked 0, running 1, stopped 0, uninterruptible 2
index 465351d4cf853e8a308c9c84abef789b3dcfa42c..cd45c8ea7463f71eccee9d82ce6a82b47bcee467 100644 (file)
@@ -28,16 +28,19 @@ cgroups. Here is what you can do.
 - Enable group scheduling in CFQ
        CONFIG_CFQ_GROUP_IOSCHED=y
 
-- Compile and boot into kernel and mount IO controller (blkio).
+- Compile and boot into kernel and mount IO controller (blkio); see
+  cgroups.txt, Why are cgroups needed?.
 
-       mount -t cgroup -o blkio none /cgroup
+       mount -t tmpfs cgroup_root /sys/fs/cgroup
+       mkdir /sys/fs/cgroup/blkio
+       mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
 
 - Create two cgroups
-       mkdir -p /cgroup/test1/ /cgroup/test2
+       mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2
 
 - Set weights of group test1 and test2
-       echo 1000 > /cgroup/test1/blkio.weight
-       echo 500 > /cgroup/test2/blkio.weight
+       echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight
+       echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight
 
 - Create two same size files (say 512MB each) on same disk (file1, file2) and
   launch two dd threads in different cgroup to read those files.
@@ -46,12 +49,12 @@ cgroups. Here is what you can do.
        echo 3 > /proc/sys/vm/drop_caches
 
        dd if=/mnt/sdb/zerofile1 of=/dev/null &
-       echo $! > /cgroup/test1/tasks
-       cat /cgroup/test1/tasks
+       echo $! > /sys/fs/cgroup/blkio/test1/tasks
+       cat /sys/fs/cgroup/blkio/test1/tasks
 
        dd if=/mnt/sdb/zerofile2 of=/dev/null &
-       echo $! > /cgroup/test2/tasks
-       cat /cgroup/test2/tasks
+       echo $! > /sys/fs/cgroup/blkio/test2/tasks
+       cat /sys/fs/cgroup/blkio/test2/tasks
 
 - At macro level, first dd should finish first. To get more precise data, keep
   on looking at (with the help of script), at blkio.disk_time and
@@ -68,13 +71,13 @@ Throttling/Upper Limit policy
 - Enable throttling in block layer
        CONFIG_BLK_DEV_THROTTLING=y
 
-- Mount blkio controller
-        mount -t cgroup -o blkio none /cgroup/blkio
+- Mount blkio controller (see cgroups.txt, Why are cgroups needed?)
+        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
 
 - Specify a bandwidth rate on particular device for root group. The format
   for policy is "<major>:<minor>  <byes_per_second>".
 
-        echo "8:16  1048576" > /cgroup/blkio/blkio.read_bps_device
+        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device
 
   Above will put a limit of 1MB/second on reads happening for root group
   on device having major/minor number 8:16.
@@ -108,7 +111,7 @@ Hierarchical Cgroups
   CFQ and throttling will practically treat all groups at same level.
 
                                pivot
-                            /  |   \  \
+                            /  /   \  \
                        root  test1 test2  test3
 
   Down the line we can implement hierarchical accounting/control support
@@ -149,7 +152,7 @@ Proportional weight policy files
 
          Following is the format.
 
-         #echo dev_maj:dev_minor weight > /path/to/cgroup/blkio.weight_device
+         # echo dev_maj:dev_minor weight > blkio.weight_device
          Configure weight=300 on /dev/sdb (8:16) in this cgroup
          # echo 8:16 300 > blkio.weight_device
          # cat blkio.weight_device
index 0ed99f08f1f39256bd71067059627ddc9a0203ac..cd67e90003c0e547952de41086f01d59ecb9a493 100644 (file)
@@ -138,11 +138,11 @@ With the ability to classify tasks differently for different resources
 the admin can easily set up a script which receives exec notifications
 and depending on who is launching the browser he can
 
-       # echo browser_pid > /mnt/<restype>/<userclass>/tasks
+    # echo browser_pid > /sys/fs/cgroup/<restype>/<userclass>/tasks
 
 With only a single hierarchy, he now would potentially have to create
 a separate cgroup for every browser launched and associate it with
-approp network and other resource class.  This may lead to
+appropriate network and other resource class.  This may lead to
 proliferation of such cgroups.
 
 Also lets say that the administrator would like to give enhanced network
@@ -153,9 +153,9 @@ apps enhanced CPU power,
 With ability to write pids directly to resource classes, it's just a
 matter of :
 
-       # echo pid > /mnt/network/<new_class>/tasks
+       # echo pid > /sys/fs/cgroup/network/<new_class>/tasks
        (after some time)
-       # echo pid > /mnt/network/<orig_class>/tasks
+       # echo pid > /sys/fs/cgroup/network/<orig_class>/tasks
 
 Without this ability, he would have to split the cgroup into
 multiple separate ones and then associate the new cgroups with the
@@ -310,21 +310,24 @@ subsystem, this is the case for the cpuset.
 To start a new job that is to be contained within a cgroup, using
 the "cpuset" cgroup subsystem, the steps are something like:
 
- 1) mkdir /dev/cgroup
- 2) mount -t cgroup -ocpuset cpuset /dev/cgroup
- 3) Create the new cgroup by doing mkdir's and write's (or echo's) in
-    the /dev/cgroup virtual file system.
- 4) Start a task that will be the "founding father" of the new job.
- 5) Attach that task to the new cgroup by writing its pid to the
-    /dev/cgroup tasks file for that cgroup.
- 6) fork, exec or clone the job tasks from this founding father task.
+ 1) mount -t tmpfs cgroup_root /sys/fs/cgroup
+ 2) mkdir /sys/fs/cgroup/cpuset
+ 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+ 4) Create the new cgroup by doing mkdir's and write's (or echo's) in
+    the /sys/fs/cgroup virtual file system.
+ 5) Start a task that will be the "founding father" of the new job.
+ 6) Attach that task to the new cgroup by writing its pid to the
+    /sys/fs/cgroup/cpuset/tasks file for that cgroup.
+ 7) fork, exec or clone the job tasks from this founding father task.
 
 For example, the following sequence of commands will setup a cgroup
 named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
 and then start a subshell 'sh' in that cgroup:
 
-  mount -t cgroup cpuset -ocpuset /dev/cgroup
-  cd /dev/cgroup
+  mount -t tmpfs cgroup_root /sys/fs/cgroup
+  mkdir /sys/fs/cgroup/cpuset
+  mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
   mkdir Charlie
   cd Charlie
   /bin/echo 2-3 > cpuset.cpus
@@ -345,7 +348,7 @@ Creating, modifying, using the cgroups can be done through the cgroup
 virtual filesystem.
 
 To mount a cgroup hierarchy with all available subsystems, type:
-# mount -t cgroup xxx /dev/cgroup
+# mount -t cgroup xxx /sys/fs/cgroup
 
 The "xxx" is not interpreted by the cgroup code, but will appear in
 /proc/mounts so may be any useful identifying string that you like.
@@ -354,23 +357,32 @@ Note: Some subsystems do not work without some user input first.  For instance,
 if cpusets are enabled the user will have to populate the cpus and mems files
 for each new cgroup created before that group can be used.
 
+As explained in section `1.2 Why are cgroups needed?' you should create
+different hierarchies of cgroups for each single resource or group of
+resources you want to control. Therefore, you should mount a tmpfs on
+/sys/fs/cgroup and create directories for each cgroup resource or resource
+group.
+
+# mount -t tmpfs cgroup_root /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/rg1
+
 To mount a cgroup hierarchy with just the cpuset and memory
 subsystems, type:
-# mount -t cgroup -o cpuset,memory hier1 /dev/cgroup
+# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1
 
 To change the set of subsystems bound to a mounted hierarchy, just
 remount with different options:
-# mount -o remount,cpuset,blkio hier1 /dev/cgroup
+# mount -o remount,cpuset,blkio hier1 /sys/fs/cgroup/rg1
 
 Now memory is removed from the hierarchy and blkio is added.
 
 Note this will add blkio to the hierarchy but won't remove memory or
 cpuset, because the new options are appended to the old ones:
-# mount -o remount,blkio /dev/cgroup
+# mount -o remount,blkio /sys/fs/cgroup/rg1
 
 To Specify a hierarchy's release_agent:
 # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
-  xxx /dev/cgroup
+  xxx /sys/fs/cgroup/rg1
 
 Note that specifying 'release_agent' more than once will return failure.
 
@@ -379,17 +391,17 @@ when the hierarchy consists of a single (root) cgroup. Supporting
 the ability to arbitrarily bind/unbind subsystems from an existing
 cgroup hierarchy is intended to be implemented in the future.
 
-Then under /dev/cgroup you can find a tree that corresponds to the
-tree of the cgroups in the system. For instance, /dev/cgroup
+Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the
+tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1
 is the cgroup that holds the whole system.
 
 If you want to change the value of release_agent:
-# echo "/sbin/new_release_agent" > /dev/cgroup/release_agent
+# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent
 
 It can also be changed via remount.
 
-If you want to create a new cgroup under /dev/cgroup:
-# cd /dev/cgroup
+If you want to create a new cgroup under /sys/fs/cgroup/rg1:
+# cd /sys/fs/cgroup/rg1
 # mkdir my_cgroup
 
 Now you want to do something with this cgroup.
index 8b930946c52a7dec05657470016946b1c3492123..9ad85df4b983e9da4ab967f098b39376c2ac0162 100644 (file)
@@ -10,26 +10,25 @@ directly present in its group.
 
 Accounting groups can be created by first mounting the cgroup filesystem.
 
-# mkdir /cgroups
-# mount -t cgroup -ocpuacct none /cgroups
-
-With the above step, the initial or the parent accounting group
-becomes visible at /cgroups. At bootup, this group includes all the
-tasks in the system. /cgroups/tasks lists the tasks in this cgroup.
-/cgroups/cpuacct.usage gives the CPU time (in nanoseconds) obtained by
-this group which is essentially the CPU time obtained by all the tasks
+# mount -t cgroup -ocpuacct none /sys/fs/cgroup
+
+With the above step, the initial or the parent accounting group becomes
+visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
+the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
+/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained
+by this group which is essentially the CPU time obtained by all the tasks
 in the system.
 
-New accounting groups can be created under the parent group /cgroups.
+New accounting groups can be created under the parent group /sys/fs/cgroup.
 
-# cd /cgroups
+# cd /sys/fs/cgroup
 # mkdir g1
 # echo $$ > g1
 
 The above steps create a new group g1 and move the current shell
 process (bash) into it. CPU time consumed by this bash and its children
 can be obtained from g1/cpuacct.usage and the same is accumulated in
-/cgroups/cpuacct.usage also.
+/sys/fs/cgroup/cpuacct.usage also.
 
 cpuacct.stat file lists a few statistics which further divide the
 CPU time obtained by the cgroup into user and system times. Currently
index 98a30829af7a1bb1ce74015ef3fa7170a112af27..5b0d78e55cccc98b34989493e3bd40bda3f6fc41 100644 (file)
@@ -661,21 +661,21 @@ than stress the kernel.
 
 To start a new job that is to be contained within a cpuset, the steps are:
 
- 1) mkdir /dev/cpuset
- 2) mount -t cgroup -ocpuset cpuset /dev/cpuset
+ 1) mkdir /sys/fs/cgroup/cpuset
+ 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
  3) Create the new cpuset by doing mkdir's and write's (or echo's) in
-    the /dev/cpuset virtual file system.
+    the /sys/fs/cgroup/cpuset virtual file system.
  4) Start a task that will be the "founding father" of the new job.
  5) Attach that task to the new cpuset by writing its pid to the
-    /dev/cpuset tasks file for that cpuset.
+    /sys/fs/cgroup/cpuset tasks file for that cpuset.
  6) fork, exec or clone the job tasks from this founding father task.
 
 For example, the following sequence of commands will setup a cpuset
 named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
 and then start a subshell 'sh' in that cpuset:
 
-  mount -t cgroup -ocpuset cpuset /dev/cpuset
-  cd /dev/cpuset
+  mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
   mkdir Charlie
   cd Charlie
   /bin/echo 2-3 > cpuset.cpus
@@ -710,14 +710,14 @@ Creating, modifying, using the cpusets can be done through the cpuset
 virtual filesystem.
 
 To mount it, type:
-# mount -t cgroup -o cpuset cpuset /dev/cpuset
+# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
 
-Then under /dev/cpuset you can find a tree that corresponds to the
-tree of the cpusets in the system. For instance, /dev/cpuset
+Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the
+tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset
 is the cpuset that holds the whole system.
 
-If you want to create a new cpuset under /dev/cpuset:
-# cd /dev/cpuset
+If you want to create a new cpuset under /sys/fs/cgroup/cpuset:
+# cd /sys/fs/cgroup/cpuset
 # mkdir my_cpuset
 
 Now you want to do something with this cpuset.
@@ -765,12 +765,12 @@ wrapper around the cgroup filesystem.
 
 The command
 
-mount -t cpuset X /dev/cpuset
+mount -t cpuset X /sys/fs/cgroup/cpuset
 
 is equivalent to
 
-mount -t cgroup -ocpuset,noprefix X /dev/cpuset
-echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
+mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset
+echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent
 
 2.2 Adding/removing cpus
 ------------------------
index 57ca4c89fe5c089aa6d8b9050fa5b2597e4f62b3..16624a7f82224d2f79d2a7aa2999ebe66c063baa 100644 (file)
@@ -22,16 +22,16 @@ removed from the child(ren).
 An entry is added using devices.allow, and removed using
 devices.deny.  For instance
 
-       echo 'c 1:3 mr' > /cgroups/1/devices.allow
+       echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow
 
 allows cgroup 1 to read and mknod the device usually known as
 /dev/null.  Doing
 
-       echo a > /cgroups/1/devices.deny
+       echo a > /sys/fs/cgroup/1/devices.deny
 
 will remove the default 'a *:* rwm' entry. Doing
 
-       echo a > /cgroups/1/devices.allow
+       echo a > /sys/fs/cgroup/1/devices.allow
 
 will add the 'a *:* rwm' entry to the whitelist.
 
index 41f37fea1276839b80cd4c220af27963f52c6a1d..c21d77742a0799424b09466857681ddcc7100f8b 100644 (file)
@@ -59,28 +59,28 @@ is non-freezable.
 
 * Examples of usage :
 
-   # mkdir /containers
-   # mount -t cgroup -ofreezer freezer  /containers
-   # mkdir /containers/0
-   # echo $some_pid > /containers/0/tasks
+   # mkdir /sys/fs/cgroup/freezer
+   # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer
+   # mkdir /sys/fs/cgroup/freezer/0
+   # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks
 
 to get status of the freezer subsystem :
 
-   # cat /containers/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    THAWED
 
 to freeze all tasks in the container :
 
-   # echo FROZEN > /containers/0/freezer.state
-   # cat /containers/0/freezer.state
+   # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    FREEZING
-   # cat /containers/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    FROZEN
 
 to unfreeze all tasks in the container :
 
-   # echo THAWED > /containers/0/freezer.state
-   # cat /containers/0/freezer.state
+   # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    THAWED
 
 This is the basic mechanism which should do the right thing for user space task
index 7c163477fcd8f001fb217cc66e4c67812af907a7..06eb6d957c83097b85fd15e87e94b8ed7edfe1cf 100644 (file)
@@ -1,8 +1,8 @@
 Memory Resource Controller
 
-NOTE: The Memory Resource Controller has been generically been referred
-      to as the memory controller in this document. Do not confuse memory
-      controller used here with the memory controller that is used in hardware.
+NOTE: The Memory Resource Controller has generically been referred to as the
+      memory controller in this document. Do not confuse memory controller
+      used here with the memory controller that is used in hardware.
 
 (For editors)
 In this document:
@@ -70,6 +70,7 @@ Brief summary of control files.
                                 (See sysctl's vm.swappiness)
  memory.move_charge_at_immigrate # set/show controls of moving charges
  memory.oom_control             # set/show oom controls.
+ memory.numa_stat               # show the number of memory usage per numa node
 
 1. History
 
@@ -181,7 +182,7 @@ behind this approach is that a cgroup that aggressively uses a shared
 page will eventually get charged for it (once it is uncharged from
 the cgroup that brought it in -- this will happen on memory pressure).
 
-Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used..
+Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.
 When you do swapoff and make swapped-out pages of shmem(tmpfs) to
 be backed into memory in force, charges for pages are accounted against the
 caller of swapoff rather than the users of shmem.
@@ -213,7 +214,7 @@ affecting global LRU, memory+swap limit is better than just limiting swap from
 OS point of view.
 
 * What happens when a cgroup hits memory.memsw.limit_in_bytes
-When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out
+When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out
 in this cgroup. Then, swap-out will not be done by cgroup routine and file
 caches are dropped. But as mentioned above, global LRU can do swapout memory
 from it for sanity of the system's memory management state. You can't forbid
@@ -263,16 +264,17 @@ b. Enable CONFIG_RESOURCE_COUNTERS
 c. Enable CONFIG_CGROUP_MEM_RES_CTLR
 d. Enable CONFIG_CGROUP_MEM_RES_CTLR_SWAP (to use swap extension)
 
-1. Prepare the cgroups
-# mkdir -p /cgroups
-# mount -t cgroup none /cgroups -o memory
+1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?)
+# mount -t tmpfs none /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/memory
+# mount -t cgroup none /sys/fs/cgroup/memory -o memory
 
 2. Make the new group and move bash into it
-# mkdir /cgroups/0
-# echo $$ > /cgroups/0/tasks
+# mkdir /sys/fs/cgroup/memory/0
+# echo $$ > /sys/fs/cgroup/memory/0/tasks
 
 Since now we're in the 0 cgroup, we can alter the memory limit:
-# echo 4M > /cgroups/0/memory.limit_in_bytes
+# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes
 
 NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo,
 mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
@@ -280,11 +282,11 @@ mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
 NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited).
 NOTE: We cannot set limits on the root cgroup any more.
 
-# cat /cgroups/0/memory.limit_in_bytes
+# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes
 4194304
 
 We can check the usage:
-# cat /cgroups/0/memory.usage_in_bytes
+# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes
 1216512
 
 A successful write to this file does not guarantee a successful set of
@@ -464,6 +466,24 @@ value for efficient access. (Of course, when necessary, it's synchronized.)
 If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
 value in memory.stat(see 5.2).
 
+5.6 numa_stat
+
+This is similar to numa_maps but operates on a per-memcg basis.  This is
+useful for providing visibility into the numa locality information within
+an memcg since the pages are allowed to be allocated from any physical
+node.  One of the usecases is evaluating application performance by
+combining this information with the application's cpu allocation.
+
+We export "total", "file", "anon" and "unevictable" pages per-node for
+each memcg.  The ouput format of memory.numa_stat is:
+
+total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
+file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
+anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+
+And we have total = file + anon + unevictable.
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
@@ -471,13 +491,13 @@ The hierarchy is created by creating the appropriate cgroups in the
 cgroup filesystem. Consider for example, the following cgroup filesystem
 hierarchy
 
-               root
+              root
             /  |   \
-             |    \
-         a     b       c
-                       | \
-                       |  \
-                       d   e
+            /  |    \
+          a    b     c
+                     | \
+                     |  \
+                     d   e
 
 In the diagram above, with hierarchical accounting enabled, all memory
 usage of e, is accounted to its ancestors up until the root (i.e, c and root),
index 1a9446b59153d8e4dd9f2bc787714a8179eb5bb4..72e238465b0b6ca452ee4905dc097007b9ff3dc0 100644 (file)
@@ -481,23 +481,6 @@ Who:       FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 
 ----------------------------
 
-What:   namespace cgroup (ns_cgroup)
-When:   2.6.38
-Why:    The ns_cgroup leads to some problems:
-       * cgroup creation is out-of-control
-       * cgroup name can conflict when pids are looping
-       * it is not possible to have a single process handling
-       a lot of namespaces without falling in a exponential creation time
-       * we may want to create a namespace without creating a cgroup
-
-       The ns_cgroup is replaced by a compatibility flag 'clone_children',
-       where a newly created cgroup will copy the parent cgroup values.
-       The userspace has to manually create a cgroup and add a task to
-       the 'tasks' file.
-Who:    Daniel Lezcano <daniel.lezcano@free.fr>
-
-----------------------------
-
 What:  iwlwifi disable_hw_scan module parameters
 When:  2.6.40
 Why:   Hareware scan is the prefer method for iwlwifi devices for
index 090e6ee04536285398a81257e1f9a1f9d34e398d..51063e681ca4f8cc0b628d2a46503ad1762aeaf5 100644 (file)
@@ -11,7 +11,9 @@ with the difference that the orphan objects are not freed but only
 reported via /sys/kernel/debug/kmemleak. A similar method is used by the
 Valgrind tool (memcheck --leak-check) to detect the memory leaks in
 user-space applications.
-Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze and tile.
+
+Please check DEBUG_KMEMLEAK dependencies in lib/Kconfig.debug for supported
+architectures.
 
 Usage
 -----
index 1b5a5ddbc3ef9a5211f3e7eeb487e524ac6ac0ac..5df176ed59b826e8cbeaca7c96d6ed6d06759fa8 100644 (file)
@@ -9,7 +9,121 @@ If variable is of Type,               use printk format specifier:
                size_t                  %zu or %zx
                ssize_t                 %zd or %zx
 
-Raw pointer value SHOULD be printed with %p.
+Raw pointer value SHOULD be printed with %p. The kernel supports
+the following extended format specifiers for pointer types:
+
+Symbols/Function Pointers:
+
+       %pF     versatile_init+0x0/0x110
+       %pf     versatile_init
+       %pS     versatile_init+0x0/0x110
+       %ps     versatile_init
+       %pB     prev_fn_of_versatile_init+0x88/0x88
+
+       For printing symbols and function pointers. The 'S' and 's' specifiers
+       result in the symbol name with ('S') or without ('s') offsets. Where
+       this is used on a kernel without KALLSYMS - the symbol address is
+       printed instead.
+
+       The 'B' specifier results in the symbol name with offsets and should be
+       used when printing stack backtraces. The specifier takes into
+       consideration the effect of compiler optimisations which may occur
+       when tail-call's are used and marked with the noreturn GCC attribute.
+
+       On ia64, ppc64 and parisc64 architectures function pointers are
+       actually function descriptors which must first be resolved. The 'F' and
+       'f' specifiers perform this resolution and then provide the same
+       functionality as the 'S' and 's' specifiers.
+
+Kernel Pointers:
+
+       %pK     0x01234567 or 0x0123456789abcdef
+
+       For printing kernel pointers which should be hidden from unprivileged
+       users. The behaviour of %pK depends on the kptr_restrict sysctl - see
+       Documentation/sysctl/kernel.txt for more details.
+
+Struct Resources:
+
+       %pr     [mem 0x60000000-0x6fffffff flags 0x2200] or
+               [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
+       %pR     [mem 0x60000000-0x6fffffff pref] or
+               [mem 0x0000000060000000-0x000000006fffffff pref]
+
+       For printing struct resources. The 'R' and 'r' specifiers result in a
+       printed resource with ('R') or without ('r') a decoded flags member.
+
+MAC/FDDI addresses:
+
+       %pM     00:01:02:03:04:05
+       %pMF    00-01-02-03-04-05
+       %pm     000102030405
+
+       For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm'
+       specifiers result in a printed address with ('M') or without ('m') byte
+       separators. The default byte separator is the colon (':').
+
+       Where FDDI addresses are concerned the 'F' specifier can be used after
+       the 'M' specifier to use dash ('-') separators instead of the default
+       separator.
+
+IPv4 addresses:
+
+       %pI4    1.2.3.4
+       %pi4    001.002.003.004
+       %p[Ii][hnbl]
+
+       For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4'
+       specifiers result in a printed address with ('i4') or without ('I4')
+       leading zeros.
+
+       The additional 'h', 'n', 'b', and 'l' specifiers are used to specify
+       host, network, big or little endian order addresses respectively. Where
+       no specifier is provided the default network/big endian order is used.
+
+IPv6 addresses:
+
+       %pI6    0001:0002:0003:0004:0005:0006:0007:0008
+       %pi6    00010002000300040005000600070008
+       %pI6c   1:2:3:4:5:6:7:8
+
+       For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6'
+       specifiers result in a printed address with ('I6') or without ('i6')
+       colon-separators. Leading zeros are always used.
+
+       The additional 'c' specifier can be used with the 'I' specifier to
+       print a compressed IPv6 address as described by
+       http://tools.ietf.org/html/rfc5952
+
+UUID/GUID addresses:
+
+       %pUb    00010203-0405-0607-0809-0a0b0c0d0e0f
+       %pUB    00010203-0405-0607-0809-0A0B0C0D0E0F
+       %pUl    03020100-0504-0706-0809-0a0b0c0e0e0f
+       %pUL    03020100-0504-0706-0809-0A0B0C0E0E0F
+
+       For printing 16-byte UUID/GUIDs addresses. The additional 'l', 'L',
+       'b' and 'B' specifiers are used to specify a little endian order in
+       lower ('l') or upper case ('L') hex characters - and big endian order
+       in lower ('b') or upper case ('B') hex characters.
+
+       Where no additional specifiers are used the default little endian
+       order with lower case hex characters will be printed.
+
+struct va_format:
+
+       %pV
+
+       For printing struct va_format structures. These contain a format string
+       and va_list as follows:
+
+       struct va_format {
+               const char *fmt;
+               va_list *va;
+       };
+
+       Do not use this feature without some mechanism to verify the
+       correctness of the format string and va_list arguments.
 
 u64 SHOULD be printed with %llu/%llx, (unsigned long long):
 
@@ -32,4 +146,5 @@ Reminder: sizeof() result is of type size_t.
 Thank you for your cooperation and attention.
 
 
-By Randy Dunlap <rdunlap@xenotime.net>
+By Randy Dunlap <rdunlap@xenotime.net> and
+Andrew Murray <amurray@mpc-data.co.uk>
index 99961993257a9f9cf358ca9641577e4b5b1699ff..91ecff07cede7dfbb4710273bd9824030a805258 100644 (file)
@@ -223,9 +223,10 @@ When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each
 group created using the pseudo filesystem.  See example steps below to create
 task groups and modify their CPU share using the "cgroups" pseudo filesystem.
 
-       # mkdir /dev/cpuctl
-       # mount -t cgroup -ocpu none /dev/cpuctl
-       # cd /dev/cpuctl
+       # mount -t tmpfs cgroup_root /sys/fs/cgroup
+       # mkdir /sys/fs/cgroup/cpu
+       # mount -t cgroup -ocpu none /sys/fs/cgroup/cpu
+       # cd /sys/fs/cgroup/cpu
 
        # mkdir multimedia      # create "multimedia" group of tasks
        # mkdir browser         # create "browser" group of tasks
index 605b0d40329d843f6c3b838cd4afa5e38438d31e..71b54d54998731ebcfe2c451c15066620b384aaa 100644 (file)
@@ -129,9 +129,8 @@ priority!
 Enabling CONFIG_RT_GROUP_SCHED lets you explicitly allocate real
 CPU bandwidth to task groups.
 
-This uses the /cgroup virtual file system and
-"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
-control group.
+This uses the cgroup virtual file system and "<cgroup>/cpu.rt_runtime_us"
+to control the CPU time reserved for each control group.
 
 For more information on working with control groups, you should read
 Documentation/cgroups/cgroups.txt as well.
@@ -150,7 +149,7 @@ For now, this can be simplified to just the following (but see Future plans):
 ===============
 
 There is work in progress to make the scheduling period for each group
-("/cgroup/<cgroup>/cpu.rt_period_us") configurable as well.
+("<cgroup>/cpu.rt_period_us") configurable as well.
 
 The constraint on the period is that a subgroup must have a smaller or
 equal period to its parent. But realistically its not very useful _yet_
index 12f9ba20ccb7aebd72aab882f9b6d6d7d9b4a135..550068466605b99e8beecca7a1b4a03788f2829a 100644 (file)
@@ -129,12 +129,12 @@ Limit injection to pages owned by memgroup. Specified by inode number
 of the memcg.
 
 Example:
-        mkdir /cgroup/hwpoison
+        mkdir /sys/fs/cgroup/mem/hwpoison
 
         usemem -m 100 -s 1000 &
-        echo `jobs -p` > /cgroup/hwpoison/tasks
+        echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks
 
-        memcg_ino=$(ls -id /cgroup/hwpoison | cut -f1 -d' ')
+        memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ')
         echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg
 
         page-types -p `pidof init`   --hwpoison  # shall do nothing
index 2cc3a94305030c098d0d010b23c541531607d46a..6c59eb90fdf4267a0629674f6546fb5747cc63ff 100644 (file)
@@ -3819,6 +3819,12 @@ S:       Maintained
 F:     drivers/leds/
 F:     include/linux/leds.h
 
+LEGACY EEPROM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+S:     Maintained
+F:     Documentation/misc-devices/eeprom
+F:     drivers/misc/eeprom/eeprom.c
+
 LEGO USB Tower driver
 M:     Juergen Stuber <starblue@users.sourceforge.net>
 L:     legousb-devel@lists.sourceforge.net
@@ -4144,7 +4150,7 @@ F:        include/linux/mm.h
 F:     mm/
 
 MEMORY RESOURCE CONTROLLER
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 M:     Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
 M:     KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
 L:     linux-mm@kvack.org
@@ -4889,7 +4895,7 @@ F:        mm/percpu*.c
 F:     arch/*/include/asm/percpu.h
 
 PER-TASK DELAY ACCOUNTING
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 S:     Maintained
 F:     include/linux/delayacct.h
 F:     kernel/delayacct.c
@@ -6097,7 +6103,7 @@ F:        include/target/
 F:     Documentation/target/
 
 TASKSTATS STATISTICS INTERFACE
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 S:     Maintained
 F:     Documentation/accounting/taskstats*
 F:     include/linux/taskstats*
@@ -6716,6 +6722,14 @@ S:       Maintained
 F:     Documentation/filesystems/vfat.txt
 F:     fs/fat/
 
+VIDEOBUF2 FRAMEWORK
+M:     Pawel Osciak <pawel@osciak.com>
+M:     Marek Szyprowski <m.szyprowski@samsung.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/video/videobuf2-*
+F:     include/media/videobuf2-*
+
 VIRTIO CONSOLE DRIVER
 M:     Amit Shah <amit.shah@redhat.com>
 L:     virtualization@lists.linux-foundation.org
index 376f2213079190f65196b0e3f6554f0f55834183..326f0a2d56e52922920aad724dfec0e78487986a 100644 (file)
@@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
                return -EFAULT;
 
        len = namelen;
-       if (namelen > 32)
+       if (len > 32)
                len = 32;
 
        down_read(&uts_sem);
@@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
        down_read(&uts_sem);
        res = sysinfo_table[offset];
        len = strlen(res)+1;
-       if (len > count)
+       if ((unsigned long)len > (unsigned long)count)
                len = count;
        if (copy_to_user(buf, res, len))
                err = -EFAULT;
@@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
                return 1;
 
        case GSI_GET_HWRPB:
-               if (nbytes < sizeof(*hwrpb))
+               if (nbytes > sizeof(*hwrpb))
                        return -EINVAL;
                if (copy_to_user(buffer, hwrpb, nbytes) != 0)
                        return -EFAULT;
@@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
 {
        struct rusage r;
        long ret, err;
+       unsigned int status = 0;
        mm_segment_t old_fs;
 
        if (!ur)
@@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
        old_fs = get_fs();
                
        set_fs (KERNEL_DS);
-       ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+       ret = sys_wait4(pid, (unsigned int __user *) &status, options,
+                       (struct rusage __user *) &r);
        set_fs (old_fs);
 
        if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
                return -EFAULT;
 
        err = 0;
+       err |= put_user(status, ustatus);
        err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
        err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
        err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
index f9da41921c521e216f07816eb5cab99c041f4845..942fad97e4472c8e27b98068efaafc1cc518787e 100644 (file)
@@ -691,9 +691,9 @@ proc_types:
 
                .word   0x41069260              @ ARM926EJ-S (v5TEJ)
                .word   0xff0ffff0
-               b       __arm926ejs_mmu_cache_on
-               b       __armv4_mmu_cache_off
-               b       __armv5tej_mmu_cache_flush
+               W(b)    __arm926ejs_mmu_cache_on
+               W(b)    __armv4_mmu_cache_off
+               W(b)    __armv5tej_mmu_cache_flush
 
                .word   0x00007000              @ ARM7 IDs
                .word   0x0000f000
index 889922ad229c31e8419c7f211cb5ef481e4d612a..67b5abb6f8576e3fa47d248ecea51facf7f7b5dc 100644 (file)
@@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
index 316af5479d90b0cec88b479d70f5991155d5497e..9c0ad7993986f340952c2a74352e3d24e75c1a01 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
index 8b0c717378faa6c9596b9c4b22a4d9dea1b9da65..1d01ddd33122d76fa7db12e989ed0ac09e2293d7 100644 (file)
@@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_EXT2_FS=m
index 5b5504143647fe23fafb93e0a7df67b9b5b7f8c3..721832ffe2d728476ff5395333d23795efcfba8a 100644 (file)
@@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
index 960f65514d88161389798236bb26ecd4c704b0cd..59577ad3f4efdfda65e65753054673a32614e80f 100644 (file)
@@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_LEDS_TRIGGER_BACKLIGHT=m
 CONFIG_LEDS_TRIGGER_GPIO=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_ISL1208=m
 CONFIG_RTC_DRV_PXA=m
 CONFIG_EXT2_FS=y
index a701e4226a6c85f804ce13a627de3d6d82127464..0cdd7b456cb2a072ce3902f2a6d7934967b083d7 100644 (file)
@@ -76,6 +76,9 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
        unsigned long dt_root;
        const char *model;
 
+       if (!dt_phys)
+               return NULL;
+
        devtree = phys_to_virt(dt_phys);
 
        /* check device tree validity */
index e8d88567680718167cf2fe389dbe4af3e0155887..90c62cd51ca9ffc891f7c95336b1c2017097d512 100644 (file)
@@ -435,6 +435,10 @@ __irq_usr:
        usr_entry
        kuser_cmpxchg_check
 
+#ifdef CONFIG_IRQSOFF_TRACER
+       bl      trace_hardirqs_off
+#endif
+
        get_thread_info tsk
 #ifdef CONFIG_PREEMPT
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
@@ -453,7 +457,7 @@ __irq_usr:
 #endif
 
        mov     why, #0
-       b       ret_to_user
+       b       ret_to_user_from_irq
  UNWIND(.fnend         )
 ENDPROC(__irq_usr)
 
index 1e7b04a40a3164f7226ce82907012acb231fec45..b2a27b6b0046ee6c1e0f0928c3269ab5f6c63cd2 100644 (file)
@@ -64,6 +64,7 @@ work_resched:
 ENTRY(ret_to_user)
 ret_slow_syscall:
        disable_irq                             @ disable interrupts
+ENTRY(ret_to_user_from_irq)
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
@@ -75,6 +76,7 @@ no_work_pending:
        arch_ret_to_user r1, lr
 
        restore_user_regs fast = 0, offset = 0
+ENDPROC(ret_to_user_from_irq)
 ENDPROC(ret_to_user)
 
 /*
index d52eec268b4746a006ef3badf6805b8acae5d7e1..6807cb1e76ddb119f78100aa3ccc7d59b1184721 100644 (file)
@@ -139,7 +139,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
        fs = get_fs();
        set_fs(KERNEL_DS);
 
-       for (i = -4; i < 1; i++) {
+       for (i = -4; i < 1 + !!thumb; i++) {
                unsigned int val, bad;
 
                if (thumb)
@@ -563,7 +563,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                if (!pmd_present(*pmd))
                        goto bad_access;
                pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
-               if (!pte_present(*pte) || !pte_dirty(*pte)) {
+               if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) {
                        pte_unmap_unlock(pte, ptl);
                        goto bad_access;
                }
index 4e66881c7aee748dddf82a304fb261dc89edde97..fc4e98ea7543a397e4ece003b3ff9f9d498fd42f 100644 (file)
@@ -494,7 +494,7 @@ static struct platform_device da850_mcasp_device = {
        .resource       = da850_mcasp_resources,
 };
 
-struct platform_device davinci_pcm_device = {
+static struct platform_device davinci_pcm_device = {
        .name   = "davinci-pcm-audio",
        .id     = -1,
 };
index 8f4f736aa267104455fdf2f1502e467e63bd9aad..806a2f02b9808abf870ac9b9b0e1c77d99e60bb4 100644 (file)
@@ -298,7 +298,7 @@ static void davinci_init_wdt(void)
 
 /*-------------------------------------------------------------------------*/
 
-struct platform_device davinci_pcm_device = {
+static struct platform_device davinci_pcm_device = {
        .name           = "davinci-pcm-audio",
        .id             = -1,
 };
index a0b838894ac99b27daaf413fbfbd8f78ae842066..e7221398e5af9c751d1dc8f85c1d294b2afb0f9b 100644 (file)
@@ -252,9 +252,11 @@ static struct irq_chip gpio_irqchip = {
 static void
 gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(irq);
+       struct davinci_gpio_regs __iomem *g;
        u32 mask = 0xffff;
 
+       g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc);
+
        /* we only care about one bank */
        if (irq & 1)
                mask <<= 16;
@@ -422,8 +424,7 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* set up all irqs in this bank */
                irq_set_chained_handler(bank_irq, gpio_irq_handler);
-               irq_set_chip_data(bank_irq, (__force void *)g);
-               irq_set_handler_data(bank_irq, (void *)irq);
+               irq_set_handler_data(bank_irq, (__force void *)g);
 
                for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
                        irq_set_chip(irq, &gpio_irqchip);
index 5f1f9867fc70eedff4620119fead758eb7c0e2b2..121ad1d4fa39f9a0d4f70c6cbd23021f4e62617f 100644 (file)
@@ -103,6 +103,7 @@ static void __init footbridge_timer_init(void)
        clockevents_calc_mult_shift(ce, mem_fclk_21285, 5);
        ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce);
        ce->min_delta_ns = clockevent_delta2ns(0x000004, ce);
+       ce->cpumask = cpumask_of(smp_processor_id());
 
        clockevents_register_device(ce);
 }
index 30b971d65815f342069719afca2052769ac99ba9..1be2eeb7a0a042198a73ec78a3b33278c25e533b 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/hardware/debug-8250.S>
 
 #else
+#include <mach/hardware.h>
        /* For EBSA285 debugging */
                .equ    dc21285_high, ARMCSR_BASE & 0xff000000
                .equ    dc21285_low,  ARMCSR_BASE & 0x00ffffff
@@ -36,8 +37,8 @@
                .else
                mov     \rp, #0
                .endif
-               orr     \rv, \rp, #0x42000000
-               orr     \rp, \rp, #dc21285_high
+               orr     \rv, \rp, #dc21285_high
+               orr     \rp, \rp, #0x42000000
                .endm
 
                .macro  senduart,rd,rx
index 65157a35dbba351d6751bdcb4ee483e37b25ee88..54add60f94c98c5d8d15c119e996395a13b6fc86 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 
+#include <asm/processor.h>     /* for cpu_relax() */
+
 #include <mach/mxs.h>
 
 #define OCOTP_WORD_OFFSET              0x20
index c34f3ea3017c4db1b4da624b12c1f800e24a91b0..4f50ca8f901e2bebd5de51defd425ba9e83f9ff4 100644 (file)
@@ -31,7 +31,7 @@ struct clk {
        bool reset;
        __u16 clk_val;
        __s8 usecount;
-       __u32 res_reg;
+       void __iomem * res_reg;
        __u16 res_mask;
 
        bool hw_ctrld;
index 8b85df4c8d8fcce5530535ffb2d91e15f25b636d..035fdc9dbdb03ebb50e88873a67232707d4fbc50 100644 (file)
  * the defines are used for setting up the I/O memory mapping.
  */
 
+#ifdef __ASSEMBLER__
+#define IOMEM(a) (a)
+#else
+#define IOMEM(a) (void __iomem *) a
+#endif
+
 /* NAND Flash CS0 */
 #define U300_NAND_CS0_PHYS_BASE                0x80000000
 
 #define U300_SEMI_CONFIG_BASE          0x30000000
 #endif
 
-/*
- * All the following peripherals are specified at their PHYSICAL address,
- * so if you need to access them (in the kernel), you MUST use the macros
- * defined in <asm/io.h> to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST()
- * etc.
- */
-
 /*
  * AHB peripherals
  */
 
 /* Vectored Interrupt Controller 0, servicing 32 interrupts */
 #define U300_INTCON0_BASE              (U300_AHB_PER_PHYS_BASE+0x1000)
-#define U300_INTCON0_VBASE             (U300_AHB_PER_VIRT_BASE+0x1000)
+#define U300_INTCON0_VBASE             IOMEM(U300_AHB_PER_VIRT_BASE+0x1000)
 
 /* Vectored Interrupt Controller 1, servicing 32 interrupts */
 #define U300_INTCON1_BASE              (U300_AHB_PER_PHYS_BASE+0x2000)
-#define U300_INTCON1_VBASE             (U300_AHB_PER_VIRT_BASE+0x2000)
+#define U300_INTCON1_VBASE             IOMEM(U300_AHB_PER_VIRT_BASE+0x2000)
 
 /* Memory Stick Pro (MSPRO) controller */
 #define U300_MSPRO_BASE                        (U300_AHB_PER_PHYS_BASE+0x3000)
 
 /* SYSCON */
 #define U300_SYSCON_BASE               (U300_SLOW_PER_PHYS_BASE+0x1000)
-#define U300_SYSCON_VBASE              (U300_SLOW_PER_VIRT_BASE+0x1000)
+#define U300_SYSCON_VBASE              IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000)
 
 /* Watchdog */
 #define U300_WDOG_BASE                 (U300_SLOW_PER_PHYS_BASE+0x2000)
 
 /* APP side special timer */
 #define U300_TIMER_APP_BASE            (U300_SLOW_PER_PHYS_BASE+0x4000)
-#define U300_TIMER_APP_VBASE           (U300_SLOW_PER_VIRT_BASE+0x4000)
+#define U300_TIMER_APP_VBASE           IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000)
 
 /* Keypad */
 #define U300_KEYPAD_BASE               (U300_SLOW_PER_PHYS_BASE+0x5000)
  * Virtual accessor macros for static devices
  */
 
-
 #endif
index 891cf44591e073ea4de84968d33f598595a8263c..18d7fa0603c230259ff96d3f9dc910b4a53a3b04 100644 (file)
@@ -411,8 +411,7 @@ static void __init u300_timer_init(void)
        /* Use general purpose timer 2 as clock source */
        if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC,
                        "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
-               printk(KERN_ERR "timer: failed to initialize clock "
-                      "source %s\n", clocksource_u300_1mhz.name);
+               pr_err("timer: failed to initialize U300 clock source\n");
 
        clockevents_calc_mult_shift(&clockevent_u300_1mhz,
                                    rate, APPTIMER_MIN_RANGE);
index 285edcd2da2aa9a9d6186a6c17cf053918b0b66e..9e6b93b1a04342e7883aa241ddecb02856818a0e 100644 (file)
@@ -46,12 +46,6 @@ static struct map_desc v2m_io_desc[] __initdata = {
        },
 };
 
-static void __init v2m_init_early(void)
-{
-       ct_desc->init_early();
-       versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
-}
-
 static void __init v2m_timer_init(void)
 {
        u32 scctrl;
@@ -365,6 +359,13 @@ static struct clk_lookup v2m_lookups[] = {
        },
 };
 
+static void __init v2m_init_early(void)
+{
+       ct_desc->init_early();
+       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
+       versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
+}
+
 static void v2m_power_off(void)
 {
        if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
@@ -418,8 +419,6 @@ static void __init v2m_init(void)
 {
        int i;
 
-       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
-
        platform_device_register(&v2m_pcie_i2c_device);
        platform_device_register(&v2m_ddc_i2c_device);
        platform_device_register(&v2m_flash_device);
index 8bfae964b133987e061c430a0426f951b07172fa..b0ee9ba3cfab41a52853eca727466abff88ddf27 100644 (file)
@@ -24,7 +24,9 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm);
 
 /*
  * We fork()ed a process, and we need a new context for the child
- * to run in.
+ * to run in.  We reserve version 0 for initial tasks so we will
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
  */
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
 static void flush_context(void)
 {
-       u32 ttb;
-       /* Copy TTBR1 into TTBR0 */
-       asm volatile("mrc       p15, 0, %0, c2, c0, 1\n"
-                    "mcr       p15, 0, %0, c2, c0, 0"
-                    : "=r" (ttb));
+       /* set the reserved ASID before flushing the TLB */
+       asm("mcr        p15, 0, %0, c13, c0, 1\n" : : "r" (0));
        isb();
        local_flush_tlb_all();
        if (icache_is_vivt_asid_tagged()) {
@@ -94,7 +93,7 @@ static void reset_context(void *info)
                return;
 
        smp_rmb();
-       asid = cpu_last_asid + cpu;
+       asid = cpu_last_asid + cpu + 1;
 
        flush_context();
        set_mm_context(mm, asid);
@@ -144,13 +143,13 @@ void __new_context(struct mm_struct *mm)
         * to start a new version and flush the TLB.
         */
        if (unlikely((asid & ~ASID_MASK) == 0)) {
-               asid = cpu_last_asid + smp_processor_id();
+               asid = cpu_last_asid + smp_processor_id() + 1;
                flush_context();
 #ifdef CONFIG_SMP
                smp_wmb();
                smp_call_function(reset_context, NULL, 1);
 #endif
-               cpu_last_asid += NR_CPUS - 1;
+               cpu_last_asid += NR_CPUS;
        }
 
        set_mm_context(mm, asid);
index 2c2cce9cd8c8399e02cf841298649daf72d06330..c19571c40a21ca62902d65cd01dcb8db9ea4f178 100644 (file)
@@ -330,6 +330,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
        memblock_reserve(__pa(_stext), _end - _stext);
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+       if (phys_initrd_size &&
+           !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) {
+               pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n",
+                      phys_initrd_start, phys_initrd_size);
+               phys_initrd_start = phys_initrd_size = 0;
+       }
        if (phys_initrd_size &&
            memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
                pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",
@@ -635,7 +641,8 @@ void __init mem_init(void)
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
                        "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
-                       "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n",
+                       "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
+                       "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
 
                        MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
                                (PAGE_SIZE)),
@@ -657,7 +664,8 @@ void __init mem_init(void)
 
                        MLK_ROUNDUP(__init_begin, __init_end),
                        MLK_ROUNDUP(_text, _etext),
-                       MLK_ROUNDUP(_sdata, _edata));
+                       MLK_ROUNDUP(_sdata, _edata),
+                       MLK_ROUNDUP(__bss_start, __bss_stop));
 
 #undef MLK
 #undef MLM
index e4c165ca669680eb6d74ce8e3d5822de50bbe44f..537ffcb0646d5e0c77ef8a336f4b39b07937beab 100644 (file)
@@ -146,7 +146,7 @@ __arm7tdmi_proc_info:
                .long   0
                .long   0
                .long   v4_cache_fns
-               .size   __arm7tdmi_proc_info, . - __arm7dmi_proc_info
+               .size   __arm7tdmi_proc_info, . - __arm7tdmi_proc_info
 
                .type   __triscenda7_proc_info, #object
 __triscenda7_proc_info:
index 7b7ebd4d096d9cb3939bed7a059be8514486d463..546b54da10059752195476dc6bd9fc0b1b243775 100644 (file)
@@ -116,7 +116,7 @@ __arm9tdmi_proc_info:
                .long   0
                .long   0
                .long   v4_cache_fns
-               .size   __arm9tdmi_proc_info, . - __arm9dmi_proc_info
+               .size   __arm9tdmi_proc_info, . - __arm9tdmi_proc_info
 
                .type   __p2001_proc_info, #object
 __p2001_proc_info:
index b3b566ec83d397c1074c1dcbee0d5e33542e7d9c..3c3867850a3011d1e163d347a25ffbabc4aa4dc7 100644 (file)
@@ -108,16 +108,18 @@ ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_ARM_ERRATA_430973
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
 #endif
-       mrc     p15, 0, r2, c2, c0, 1           @ load TTB 1
-       mcr     p15, 0, r2, c2, c0, 0           @ into TTB 0
+#ifdef CONFIG_ARM_ERRATA_754322
+       dsb
+#endif
+       mcr     p15, 0, r2, c13, c0, 1          @ set reserved context ID
+       isb
+1:     mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
        isb
 #ifdef CONFIG_ARM_ERRATA_754322
        dsb
 #endif
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID
        isb
-       mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
-       isb
 #endif
        mov     pc, lr
 ENDPROC(cpu_v7_switch_mm)
index 3538b85ede910a4bc32c8e85b604789809cef21d..b130f60ca6b73e9b7b8435dcc52633bb1761078c 100644 (file)
@@ -139,7 +139,7 @@ static struct sdma_script_start_addrs addr_imx35_to2 = {
 #endif
 
 #ifdef CONFIG_SOC_IMX51
-static struct sdma_script_start_addrs addr_imx51_to1 = {
+static struct sdma_script_start_addrs addr_imx51 = {
        .ap_2_ap_addr = 642,
        .uart_2_mcu_addr = 817,
        .mcu_2_app_addr = 747,
@@ -196,7 +196,9 @@ static int __init imxXX_add_imx_dma(void)
 
 #if defined(CONFIG_SOC_IMX51)
        if (cpu_is_mx51()) {
-               imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1;
+               int to_version = mx51_revision() >> 4;
+               imx51_imx_sdma_data.pdata.to_version = to_version;
+               imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51;
                ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
        } else
 #endif
index 6cb786c0baf6e0857f9fed6b70eb6ae69aac3231..77ca4f905d2cf9da872e12cb1efb4536a728a8f4 100644 (file)
@@ -110,7 +110,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S35390A=m
 CONFIG_RTC_DRV_AT32AP700X=m
 CONFIG_DMADEVICES=y
index 31d954216c054ec37748ffb942d6d3f463d8ba8b..9f1d08401fcaacdf6d53f661da44e2cee641b66e 100644 (file)
@@ -112,7 +112,7 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=m
 CONFIG_SDH_BFIN=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_BFIN=m
 CONFIG_EXT2_FS=m
 # CONFIG_DNOTIFY is not set
index 37862b2ce3633a3f87f3aeb0ce3f8e119688a143..807c97eed8a8ed48a5957c144e907894c8d8c397 100644 (file)
@@ -678,7 +678,7 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_TEST=m
 CONFIG_RTC_DRV_DS1307=m
index 7f7e4a8786029897df66ca0e49c64b2c6aa5065d..22e719575c60b33cb64cee5fcb840c2507f942c8 100644 (file)
@@ -85,7 +85,7 @@ CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PCI is not set
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
index 6472322bf13b6820af3c364c1a994baebe914fbe..185c292b0f1c8cab6968420212c9690bc895e6b3 100644 (file)
@@ -141,7 +141,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PS3=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
index 0f558914e7604cc56a6822eeb2a2dec09c510abc..e2cbd92d520b347ca8e695cb2a8392dc72ac2794 100644 (file)
@@ -227,7 +227,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_ARK3116=m
 CONFIG_USB_SERIAL_PL2303=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SH=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
index 051474c65b783c5e9f3315de2fb3732516810027..34d6a1cab8def622d95c46b138b02a7d8a0eeeec 100644 (file)
@@ -163,11 +163,32 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
         * This has the effect of treating non-periodic like periodic.
         */
        if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
-               unsigned long m, t;
+               unsigned long m, t, mc, base, k;
+               struct hpet __iomem *hpet = devp->hd_hpet;
+               struct hpets *hpetp = devp->hd_hpets;
 
                t = devp->hd_ireqfreq;
                m = read_counter(&devp->hd_timer->hpet_compare);
-               write_counter(t + m, &devp->hd_timer->hpet_compare);
+               mc = read_counter(&hpet->hpet_mc);
+               /* The time for the next interrupt would logically be t + m,
+                * however, if we are very unlucky and the interrupt is delayed
+                * for longer than t then we will completely miss the next
+                * interrupt if we set t + m and an application will hang.
+                * Therefore we need to make a more complex computation assuming
+                * that there exists a k for which the following is true:
+                * k * t + base < mc + delta
+                * (k + 1) * t + base > mc + delta
+                * where t is the interval in hpet ticks for the given freq,
+                * base is the theoretical start value 0 < base < t,
+                * mc is the main counter value at the time of the interrupt,
+                * delta is the time it takes to write the a value to the
+                * comparator.
+                * k may then be computed as (mc - base + delta) / t .
+                */
+               base = mc % t;
+               k = (mc - base + hpetp->hp_delta) / t;
+               write_counter(t * (k + 1) + base,
+                             &devp->hd_timer->hpet_compare);
        }
 
        if (devp->hd_flags & HPET_SHARED_IRQ)
index 23f0d5e99f35705c97c165e05b05a7e5239804b7..713d43b4e563396f419e9583af58b6a4ed636290 100644 (file)
@@ -1,3 +1,10 @@
+config LEDS_GPIO_REGISTER
+       bool
+       help
+         This option provides the function gpio_led_register_device.
+         As this function is used by arch code it must not be compiled as a
+         module.
+
 menuconfig NEW_LEDS
        bool "LED Support"
        help
@@ -7,22 +14,14 @@ menuconfig NEW_LEDS
          This is not related to standard keyboard LEDs which are controlled
          via the input system.
 
+if NEW_LEDS
+
 config LEDS_CLASS
        bool "LED Class Support"
-       depends on NEW_LEDS
        help
          This option enables the led sysfs class in /sys/class/leds.  You'll
          need this to do anything useful with LEDs.  If unsure, say N.
 
-config LEDS_GPIO_REGISTER
-       bool
-       help
-         This option provides the function gpio_led_register_device.
-         As this function is used by arch code it must not be compiled as a
-         module.
-
-if NEW_LEDS
-
 comment "LED drivers"
 
 config LEDS_88PM860X
@@ -391,6 +390,7 @@ config LEDS_NETXBIG
 
 config LEDS_ASIC3
        bool "LED support for the HTC ASIC3"
+       depends on LEDS_CLASS
        depends on MFD_ASIC3
        default y
        help
index 200311fea369e6a952f38b8c205a0fb5c0c01f00..e2a52e5cf449c7f65f97e3e492a8304e321a80df 100644 (file)
@@ -609,6 +609,7 @@ static int apds990x_detect(struct apds990x_chip *chip)
        return ret;
 }
 
+#if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME)
 static int apds990x_chip_on(struct apds990x_chip *chip)
 {
        int err  = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
@@ -624,6 +625,7 @@ static int apds990x_chip_on(struct apds990x_chip *chip)
        apds990x_mode_on(chip);
        return 0;
 }
+#endif
 
 static int apds990x_chip_off(struct apds990x_chip *chip)
 {
index e01e08c8c88b6cb72e3e585fec9ccfacfe79eb2e..bc685bfc4c33aaacf89a5dc7205943bd69f14f8d 100644 (file)
@@ -174,7 +174,7 @@ struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer_nr, int domain)
                timer_nr = t < max ? (int) t : -1;
        } else {
                /* check if the requested timer's available */
-               if (test_bit(timer_nr, mfgpt->avail))
+               if (!test_bit(timer_nr, mfgpt->avail))
                        timer_nr = -1;
        }
 
index 7aded90f9daa1683b7a40fa24befed62b26376da..cfbddbef11de3b67c54be85797dd124843ca8596 100644 (file)
@@ -845,7 +845,7 @@ err_iounmap:
 err_iounmap_app:
        iounmap(config->va_app_base);
 err_kzalloc:
-       kfree(config);
+       kfree(target);
 err_rel_res:
        release_mem_region(res1->start, resource_size(res1));
 err_rel_res0:
index 5da5bea0f9f09ed49eedf281da1308c04a0b7341..7721de942c69e29cd0d36300eb48a695dfbdafbf 100644 (file)
@@ -1144,9 +1144,17 @@ static int __devinit mmci_probe(struct amba_device *dev,
                else if (ret != -ENOSYS)
                        goto err_gpio_cd;
 
+               /*
+                * A gpio pin that will detect cards when inserted and removed
+                * will most likely want to trigger on the edges if it is
+                * 0 when ejected and 1 when inserted (or mutatis mutandis
+                * for the inverted case) so we request triggers on both
+                * edges.
+                */
                ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
-                                             mmci_cd_irq, 0,
-                                             DRIVER_NAME " (cd)", host);
+                               mmci_cd_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               DRIVER_NAME " (cd)", host);
                if (ret >= 0)
                        host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
        }
index 0b9b85424dfaa1fdbe7b931e6fcf98f68ef9c9bf..4cc1a5bfab40c0705c31beca87757068a7b8487d 100644 (file)
@@ -81,7 +81,6 @@ struct adis16201_state {
 
 int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
 
-#ifdef CONFIG_IIO_RING_BUFFER
 enum adis16201_scan {
        ADIS16201_SCAN_SUPPLY,
        ADIS16201_SCAN_ACC_X,
@@ -92,6 +91,7 @@ enum adis16201_scan {
        ADIS16201_SCAN_INCLI_Y,
 };
 
+#ifdef CONFIG_IIO_RING_BUFFER
 void adis16201_remove_trigger(struct iio_dev *indio_dev);
 int adis16201_probe_trigger(struct iio_dev *indio_dev);
 
index 8bb8ce50c2483d339f584a2c83ad82c771ee2108..175e21bb9b403d79a0a2810c6730712791a1a62d 100644 (file)
@@ -76,7 +76,6 @@ struct adis16203_state {
 
 int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
 
-#ifdef CONFIG_IIO_RING_BUFFER
 enum adis16203_scan {
        ADIS16203_SCAN_SUPPLY,
        ADIS16203_SCAN_AUX_ADC,
@@ -85,6 +84,7 @@ enum adis16203_scan {
        ADIS16203_SCAN_INCLI_Y,
 };
 
+#ifdef CONFIG_IIO_RING_BUFFER
 void adis16203_remove_trigger(struct iio_dev *indio_dev);
 int adis16203_probe_trigger(struct iio_dev *indio_dev);
 
index f2cb7503fcb213115b3b15722495c335a0aad984..465210930890b72ecdcaf1c70167b7211f43ed9e 100644 (file)
@@ -1397,6 +1397,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        int fifosize, base_baud;
        int port_type;
        struct pch_uart_driver_data *board;
+       const char *board_name;
 
        board = &drv_dat[id->driver_data];
        port_type = board->port_type;
@@ -1412,7 +1413,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        base_baud = 1843200; /* 1.8432MHz */
 
        /* quirk for CM-iTC board */
-       if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+       board_name = dmi_get_system_info(DMI_BOARD_NAME);
+       if (board_name && strstr(board_name, "CM-iTC"))
                base_baud = 192000000; /* 192.0MHz */
 
        switch (port_type) {
index 0c9373bedd1f39d61d8b391bcc54a630d6d981c8..2d93c8d61ad5e2aa9ea2cd48d30581aad7cf8fb4 100644 (file)
@@ -302,6 +302,18 @@ config BACKLIGHT_ADP8860
          To compile this driver as a module, choose M here: the module will
          be called adp8860_bl.
 
+config BACKLIGHT_ADP8870
+       tristate "Backlight Driver for ADP8870 using WLED"
+       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       select NEW_LEDS
+       select LEDS_CLASS
+       help
+         If you have a LCD backlight connected to the ADP8870,
+         say Y here to enable this driver.
+
+         To compile this driver as a module, choose M here: the module will
+         be called adp8870_bl.
+
 config BACKLIGHT_88PM860X
        tristate "Backlight Driver for 88PM8606 using WLED"
        depends on MFD_88PM860X
index b9ca8490df87850dc746e5a4661b67f5294589a4..ee72adb8786ed2f9f71de431987f0f5e11da7fc5 100644 (file)
@@ -34,6 +34,7 @@ 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
 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
 
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
new file mode 100644 (file)
index 0000000..05a8832
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+ * Backlight driver for Analog Devices ADP8870 Backlight Devices
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/adp8870.h>
+#define ADP8870_EXT_FEATURES
+#define ADP8870_USE_LEDS
+
+
+#define ADP8870_MFDVID 0x00  /* Manufacturer and device ID */
+#define ADP8870_MDCR   0x01  /* Device mode and status */
+#define ADP8870_INT_STAT 0x02  /* Interrupts status */
+#define ADP8870_INT_EN 0x03  /* Interrupts enable */
+#define ADP8870_CFGR   0x04  /* Configuration register */
+#define ADP8870_BLSEL  0x05  /* Sink enable backlight or independent */
+#define ADP8870_PWMLED 0x06  /* PWM Enable Selection Register */
+#define ADP8870_BLOFF  0x07  /* Backlight off timeout */
+#define ADP8870_BLDIM  0x08  /* Backlight dim timeout */
+#define ADP8870_BLFR   0x09  /* Backlight fade in and out rates */
+#define ADP8870_BLMX1  0x0A  /* Backlight (Brightness Level 1-daylight) maximum current */
+#define ADP8870_BLDM1  0x0B  /* Backlight (Brightness Level 1-daylight) dim current */
+#define ADP8870_BLMX2  0x0C  /* Backlight (Brightness Level 2-bright) maximum current */
+#define ADP8870_BLDM2  0x0D  /* Backlight (Brightness Level 2-bright) dim current */
+#define ADP8870_BLMX3  0x0E  /* Backlight (Brightness Level 3-office) maximum current */
+#define ADP8870_BLDM3  0x0F  /* Backlight (Brightness Level 3-office) dim current */
+#define ADP8870_BLMX4  0x10  /* Backlight (Brightness Level 4-indoor) maximum current */
+#define ADP8870_BLDM4  0x11  /* Backlight (Brightness Level 4-indoor) dim current */
+#define ADP8870_BLMX5  0x12  /* Backlight (Brightness Level 5-dark) maximum current */
+#define ADP8870_BLDM5  0x13  /* Backlight (Brightness Level 5-dark) dim current */
+#define ADP8870_ISCLAW 0x1A  /* Independent sink current fade law register */
+#define ADP8870_ISCC   0x1B  /* Independent sink current control register */
+#define ADP8870_ISCT1  0x1C  /* Independent Sink Current Timer Register LED[7:5] */
+#define ADP8870_ISCT2  0x1D  /* Independent Sink Current Timer Register LED[4:1] */
+#define ADP8870_ISCF   0x1E  /* Independent sink current fade register */
+#define ADP8870_ISC1   0x1F  /* Independent Sink Current LED1 */
+#define ADP8870_ISC2   0x20  /* Independent Sink Current LED2 */
+#define ADP8870_ISC3   0x21  /* Independent Sink Current LED3 */
+#define ADP8870_ISC4   0x22  /* Independent Sink Current LED4 */
+#define ADP8870_ISC5   0x23  /* Independent Sink Current LED5 */
+#define ADP8870_ISC6   0x24  /* Independent Sink Current LED6 */
+#define ADP8870_ISC7   0x25  /* Independent Sink Current LED7 (Brightness Level 1-daylight) */
+#define ADP8870_ISC7_L2        0x26  /* Independent Sink Current LED7 (Brightness Level 2-bright) */
+#define ADP8870_ISC7_L3        0x27  /* Independent Sink Current LED7 (Brightness Level 3-office) */
+#define ADP8870_ISC7_L4        0x28  /* Independent Sink Current LED7 (Brightness Level 4-indoor) */
+#define ADP8870_ISC7_L5        0x29  /* Independent Sink Current LED7 (Brightness Level 5-dark) */
+#define ADP8870_CMP_CTL        0x2D  /* ALS Comparator Control Register */
+#define ADP8870_ALS1_EN        0x2E  /* Main ALS comparator level enable */
+#define ADP8870_ALS2_EN        0x2F  /* Second ALS comparator level enable */
+#define ADP8870_ALS1_STAT 0x30  /* Main ALS Comparator Status Register */
+#define ADP8870_ALS2_STAT 0x31  /* Second ALS Comparator Status Register */
+#define ADP8870_L2TRP  0x32  /* L2 comparator reference */
+#define ADP8870_L2HYS  0x33  /* L2 hysteresis */
+#define ADP8870_L3TRP  0x34  /* L3 comparator reference */
+#define ADP8870_L3HYS  0x35  /* L3 hysteresis */
+#define ADP8870_L4TRP  0x36  /* L4 comparator reference */
+#define ADP8870_L4HYS  0x37  /* L4 hysteresis */
+#define ADP8870_L5TRP  0x38  /* L5 comparator reference */
+#define ADP8870_L5HYS  0x39  /* L5 hysteresis */
+#define ADP8870_PH1LEVL        0x40  /* First phototransistor ambient light level-low byte register */
+#define ADP8870_PH1LEVH        0x41  /* First phototransistor ambient light level-high byte register */
+#define ADP8870_PH2LEVL        0x42  /* Second phototransistor ambient light level-low byte register */
+#define ADP8870_PH2LEVH        0x43  /* Second phototransistor ambient light level-high byte register */
+
+#define ADP8870_MANUFID                0x3  /* Analog Devices AD8870 Manufacturer and device ID */
+#define ADP8870_DEVID(x)       ((x) & 0xF)
+#define ADP8870_MANID(x)       ((x) >> 4)
+
+/* MDCR Device mode and status */
+#define D7ALSEN                        (1 << 7)
+#define INT_CFG                        (1 << 6)
+#define NSTBY                  (1 << 5)
+#define DIM_EN                 (1 << 4)
+#define GDWN_DIS               (1 << 3)
+#define SIS_EN                 (1 << 2)
+#define CMP_AUTOEN             (1 << 1)
+#define BLEN                   (1 << 0)
+
+/* ADP8870_ALS1_EN Main ALS comparator level enable */
+#define L5_EN                  (1 << 3)
+#define L4_EN                  (1 << 2)
+#define L3_EN                  (1 << 1)
+#define L2_EN                  (1 << 0)
+
+#define CFGR_BLV_SHIFT         3
+#define CFGR_BLV_MASK          0x7
+#define ADP8870_FLAG_LED_MASK  0xFF
+
+#define FADE_VAL(in, out)      ((0xF & (in)) | ((0xF & (out)) << 4))
+#define BL_CFGR_VAL(law, blv)  ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
+#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1)
+
+struct adp8870_bl {
+       struct i2c_client *client;
+       struct backlight_device *bl;
+       struct adp8870_led *led;
+       struct adp8870_backlight_platform_data *pdata;
+       struct mutex lock;
+       unsigned long cached_daylight_max;
+       int id;
+       int revid;
+       int current_brightness;
+};
+
+struct adp8870_led {
+       struct led_classdev     cdev;
+       struct work_struct      work;
+       struct i2c_client       *client;
+       enum led_brightness     new_brightness;
+       int                     id;
+       int                     flags;
+};
+
+static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
+               return ret;
+       }
+
+       *val = ret;
+       return 0;
+}
+
+
+static int adp8870_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       int ret = i2c_smbus_write_byte_data(client, reg, val);
+       if (ret)
+               dev_err(&client->dev, "failed to write\n");
+
+       return ret;
+}
+
+static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       uint8_t reg_val;
+       int ret;
+
+       mutex_lock(&data->lock);
+
+       ret = adp8870_read(client, reg, &reg_val);
+
+       if (!ret && ((reg_val & bit_mask) == 0)) {
+               reg_val |= bit_mask;
+               ret = adp8870_write(client, reg, reg_val);
+       }
+
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       uint8_t reg_val;
+       int ret;
+
+       mutex_lock(&data->lock);
+
+       ret = adp8870_read(client, reg, &reg_val);
+
+       if (!ret && (reg_val & bit_mask)) {
+               reg_val &= ~bit_mask;
+               ret = adp8870_write(client, reg, reg_val);
+       }
+
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+/*
+ * Independent sink / LED
+ */
+#if defined(ADP8870_USE_LEDS)
+static void adp8870_led_work(struct work_struct *work)
+{
+       struct adp8870_led *led = container_of(work, struct adp8870_led, work);
+       adp8870_write(led->client, ADP8870_ISC1 + led->id - 1,
+                        led->new_brightness >> 1);
+}
+
+static void adp8870_led_set(struct led_classdev *led_cdev,
+                          enum led_brightness value)
+{
+       struct adp8870_led *led;
+
+       led = container_of(led_cdev, struct adp8870_led, cdev);
+       led->new_brightness = value;
+       /*
+        * Use workqueue for IO since I2C operations can sleep.
+        */
+       schedule_work(&led->work);
+}
+
+static int adp8870_led_setup(struct adp8870_led *led)
+{
+       struct i2c_client *client = led->client;
+       int ret = 0;
+
+       ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0);
+       if (ret)
+               return ret;
+
+       ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1));
+       if (ret)
+               return ret;
+
+       if (led->id > 4)
+               ret = adp8870_set_bits(client, ADP8870_ISCT1,
+                               (led->flags & 0x3) << ((led->id - 5) * 2));
+       else
+               ret = adp8870_set_bits(client, ADP8870_ISCT2,
+                               (led->flags & 0x3) << ((led->id - 1) * 2));
+
+       return ret;
+}
+
+static int __devinit adp8870_led_probe(struct i2c_client *client)
+{
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       struct adp8870_led *led, *led_dat;
+       struct led_info *cur_led;
+       int ret, i;
+
+
+       led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
+       if (led == NULL) {
+               dev_err(&client->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
+       if (ret)
+               goto err_free;
+
+       ret = adp8870_write(client, ADP8870_ISCT1,
+                       (pdata->led_on_time & 0x3) << 6);
+       if (ret)
+               goto err_free;
+
+       ret = adp8870_write(client, ADP8870_ISCF,
+                       FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
+       if (ret)
+               goto err_free;
+
+       for (i = 0; i < pdata->num_leds; ++i) {
+               cur_led = &pdata->leds[i];
+               led_dat = &led[i];
+
+               led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK;
+
+               if (led_dat->id > 7 || led_dat->id < 1) {
+                       dev_err(&client->dev, "Invalid LED ID %d\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
+                       dev_err(&client->dev, "LED %d used by Backlight\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               led_dat->cdev.name = cur_led->name;
+               led_dat->cdev.default_trigger = cur_led->default_trigger;
+               led_dat->cdev.brightness_set = adp8870_led_set;
+               led_dat->cdev.brightness = LED_OFF;
+               led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT;
+               led_dat->client = client;
+               led_dat->new_brightness = LED_OFF;
+               INIT_WORK(&led_dat->work, adp8870_led_work);
+
+               ret = led_classdev_register(&client->dev, &led_dat->cdev);
+               if (ret) {
+                       dev_err(&client->dev, "failed to register LED %d\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               ret = adp8870_led_setup(led_dat);
+               if (ret) {
+                       dev_err(&client->dev, "failed to write\n");
+                       i++;
+                       goto err;
+               }
+       }
+
+       data->led = led;
+
+       return 0;
+
+ err:
+       for (i = i - 1; i >= 0; --i) {
+               led_classdev_unregister(&led[i].cdev);
+               cancel_work_sync(&led[i].work);
+       }
+
+ err_free:
+       kfree(led);
+
+       return ret;
+}
+
+static int __devexit adp8870_led_remove(struct i2c_client *client)
+{
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < pdata->num_leds; i++) {
+               led_classdev_unregister(&data->led[i].cdev);
+               cancel_work_sync(&data->led[i].work);
+       }
+
+       kfree(data->led);
+       return 0;
+}
+#else
+static int __devinit adp8870_led_probe(struct i2c_client *client)
+{
+       return 0;
+}
+
+static int __devexit adp8870_led_remove(struct i2c_client *client)
+{
+       return 0;
+}
+#endif
+
+static int adp8870_bl_set(struct backlight_device *bl, int brightness)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+       struct i2c_client *client = data->client;
+       int ret = 0;
+
+       if (data->pdata->en_ambl_sens) {
+               if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) {
+                       /* Disable Ambient Light auto adjust */
+                       ret = adp8870_clr_bits(client, ADP8870_MDCR,
+                                       CMP_AUTOEN);
+                       if (ret)
+                               return ret;
+                       ret = adp8870_write(client, ADP8870_BLMX1, brightness);
+                       if (ret)
+                               return ret;
+               } else {
+                       /*
+                        * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
+                        * restore daylight l1 sysfs brightness
+                        */
+                       ret = adp8870_write(client, ADP8870_BLMX1,
+                                        data->cached_daylight_max);
+                       if (ret)
+                               return ret;
+
+                       ret = adp8870_set_bits(client, ADP8870_MDCR,
+                                        CMP_AUTOEN);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               ret = adp8870_write(client, ADP8870_BLMX1, brightness);
+               if (ret)
+                       return ret;
+       }
+
+       if (data->current_brightness && brightness == 0)
+               ret = adp8870_set_bits(client,
+                               ADP8870_MDCR, DIM_EN);
+       else if (data->current_brightness == 0 && brightness)
+               ret = adp8870_clr_bits(client,
+                               ADP8870_MDCR, DIM_EN);
+
+       if (!ret)
+               data->current_brightness = brightness;
+
+       return ret;
+}
+
+static int adp8870_bl_update_status(struct backlight_device *bl)
+{
+       int brightness = bl->props.brightness;
+       if (bl->props.power != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       return adp8870_bl_set(bl, brightness);
+}
+
+static int adp8870_bl_get_brightness(struct backlight_device *bl)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+
+       return data->current_brightness;
+}
+
+static const struct backlight_ops adp8870_bl_ops = {
+       .update_status  = adp8870_bl_update_status,
+       .get_brightness = adp8870_bl_get_brightness,
+};
+
+static int adp8870_bl_setup(struct backlight_device *bl)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+       struct i2c_client *client = data->client;
+       struct adp8870_backlight_platform_data *pdata = data->pdata;
+       int ret = 0;
+
+       ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim);
+       if (ret)
+               return ret;
+
+       if (pdata->en_ambl_sens) {
+               data->cached_daylight_max = pdata->l1_daylight_max;
+               ret = adp8870_write(client, ADP8870_BLMX2,
+                                               pdata->l2_bright_max);
+               if (ret)
+                       return ret;
+               ret = adp8870_write(client, ADP8870_BLDM2,
+                                               pdata->l2_bright_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX3,
+                                               pdata->l3_office_max);
+               if (ret)
+                       return ret;
+               ret = adp8870_write(client, ADP8870_BLDM3,
+                                               pdata->l3_office_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX4,
+                                               pdata->l4_indoor_max);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLDM4,
+                                               pdata->l4_indor_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX5,
+                                               pdata->l5_dark_max);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLDM5,
+                                               pdata->l5_dark_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN |
+                                               L3_EN | L2_EN);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_CMP_CTL,
+                       ALS_CMPR_CFG_VAL(pdata->abml_filt));
+               if (ret)
+                       return ret;
+       }
+
+       ret = adp8870_write(client, ADP8870_CFGR,
+                       BL_CFGR_VAL(pdata->bl_fade_law, 0));
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in,
+                       pdata->bl_fade_out));
+       if (ret)
+               return ret;
+       /*
+        * ADP8870 Rev0 requires GDWN_DIS bit set
+        */
+
+       ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY |
+                       (data->revid == 0 ? GDWN_DIS : 0));
+
+       return ret;
+}
+
+static ssize_t adp8870_show(struct device *dev, char *buf, int reg)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, reg, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       return sprintf(buf, "%u\n", reg_val);
+}
+
+static ssize_t adp8870_store(struct device *dev, const char *buf,
+                        size_t count, int reg)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&data->lock);
+       adp8870_write(data->client, reg, val);
+       mutex_unlock(&data->lock);
+
+       return count;
+}
+
+static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX5);
+}
+
+static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX5);
+}
+static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show,
+                       adp8870_bl_l5_dark_max_store);
+
+
+static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX4);
+}
+
+static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX4);
+}
+static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show,
+                       adp8870_bl_l4_indoor_max_store);
+
+
+static ssize_t adp8870_bl_l3_office_max_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX3);
+}
+
+static ssize_t adp8870_bl_l3_office_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX3);
+}
+
+static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show,
+                       adp8870_bl_l3_office_max_store);
+
+static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX2);
+}
+
+static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX2);
+}
+static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show,
+                       adp8870_bl_l2_bright_max_store);
+
+static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX1);
+}
+
+static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
+       if (ret)
+               return ret;
+
+       return adp8870_store(dev, buf, count, ADP8870_BLMX1);
+}
+static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show,
+                       adp8870_bl_l1_daylight_max_store);
+
+static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM5);
+}
+
+static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM5);
+}
+static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show,
+                       adp8870_bl_l5_dark_dim_store);
+
+static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM4);
+}
+
+static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM4);
+}
+static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show,
+                       adp8870_bl_l4_indoor_dim_store);
+
+
+static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM3);
+}
+
+static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM3);
+}
+static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show,
+                       adp8870_bl_l3_office_dim_store);
+
+static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM2);
+}
+
+static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM2);
+}
+static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show,
+                       adp8870_bl_l2_bright_dim_store);
+
+static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM1);
+}
+
+static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM1);
+}
+static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show,
+                       adp8870_bl_l1_daylight_dim_store);
+
+#ifdef ADP8870_EXT_FEATURES
+static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+       uint16_t ret_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, ADP8870_PH1LEVL, &reg_val);
+       if (error < 0) {
+               mutex_unlock(&data->lock);
+               return error;
+       }
+       ret_val = reg_val;
+       error = adp8870_read(data->client, ADP8870_PH1LEVH, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       /* Return 13-bit conversion value for the first light sensor */
+       ret_val += (reg_val & 0x1F) << 8;
+
+       return sprintf(buf, "%u\n", ret_val);
+}
+static DEVICE_ATTR(ambient_light_level, 0444,
+               adp8870_bl_ambient_light_level_show, NULL);
+
+static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, ADP8870_CFGR, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       return sprintf(buf, "%u\n",
+               ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1);
+}
+
+static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       unsigned long val;
+       uint8_t reg_val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val == 0) {
+               /* Enable automatic ambient light sensing */
+               adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
+       } else if ((val > 0) && (val < 6)) {
+               /* Disable automatic ambient light sensing */
+               adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
+
+               /* Set user supplied ambient light zone */
+               mutex_lock(&data->lock);
+               adp8870_read(data->client, ADP8870_CFGR, &reg_val);
+               reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
+               reg_val |= (val - 1) << CFGR_BLV_SHIFT;
+               adp8870_write(data->client, ADP8870_CFGR, reg_val);
+               mutex_unlock(&data->lock);
+       }
+
+       return count;
+}
+static DEVICE_ATTR(ambient_light_zone, 0664,
+               adp8870_bl_ambient_light_zone_show,
+               adp8870_bl_ambient_light_zone_store);
+#endif
+
+static struct attribute *adp8870_bl_attributes[] = {
+       &dev_attr_l5_dark_max.attr,
+       &dev_attr_l5_dark_dim.attr,
+       &dev_attr_l4_indoor_max.attr,
+       &dev_attr_l4_indoor_dim.attr,
+       &dev_attr_l3_office_max.attr,
+       &dev_attr_l3_office_dim.attr,
+       &dev_attr_l2_bright_max.attr,
+       &dev_attr_l2_bright_dim.attr,
+       &dev_attr_l1_daylight_max.attr,
+       &dev_attr_l1_daylight_dim.attr,
+#ifdef ADP8870_EXT_FEATURES
+       &dev_attr_ambient_light_level.attr,
+       &dev_attr_ambient_light_zone.attr,
+#endif
+       NULL
+};
+
+static const struct attribute_group adp8870_bl_attr_group = {
+       .attrs = adp8870_bl_attributes,
+};
+
+static int __devinit adp8870_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct backlight_properties props;
+       struct backlight_device *bl;
+       struct adp8870_bl *data;
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       uint8_t reg_val;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "no platform data?\n");
+               return -EINVAL;
+       }
+
+       ret = adp8870_read(client, ADP8870_MFDVID, &reg_val);
+       if (ret < 0)
+               return -EIO;
+
+       if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) {
+               dev_err(&client->dev, "failed to probe\n");
+               return -ENODEV;
+       }
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->revid = ADP8870_DEVID(reg_val);
+       data->client = client;
+       data->pdata = pdata;
+       data->id = id->driver_data;
+       data->current_brightness = 0;
+       i2c_set_clientdata(client, data);
+
+       mutex_init(&data->lock);
+
+       memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS;
+       bl = backlight_device_register(dev_driver_string(&client->dev),
+                       &client->dev, data, &adp8870_bl_ops, &props);
+       if (IS_ERR(bl)) {
+               dev_err(&client->dev, "failed to register backlight\n");
+               ret = PTR_ERR(bl);
+               goto out2;
+       }
+
+       data->bl = bl;
+
+       if (pdata->en_ambl_sens)
+               ret = sysfs_create_group(&bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+
+       if (ret) {
+               dev_err(&client->dev, "failed to register sysfs\n");
+               goto out1;
+       }
+
+       ret = adp8870_bl_setup(bl);
+       if (ret) {
+               ret = -EIO;
+               goto out;
+       }
+
+       backlight_update_status(bl);
+
+       dev_info(&client->dev, "Rev.%d Backlight\n", data->revid);
+
+       if (pdata->num_leds)
+               adp8870_led_probe(client);
+
+       return 0;
+
+out:
+       if (data->pdata->en_ambl_sens)
+               sysfs_remove_group(&data->bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+out1:
+       backlight_device_unregister(bl);
+out2:
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
+
+       return ret;
+}
+
+static int __devexit adp8870_remove(struct i2c_client *client)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+
+       adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
+
+       if (data->led)
+               adp8870_led_remove(client);
+
+       if (data->pdata->en_ambl_sens)
+               sysfs_remove_group(&data->bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+
+       backlight_device_unregister(data->bl);
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message)
+{
+       adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
+
+       return 0;
+}
+
+static int adp8870_i2c_resume(struct i2c_client *client)
+{
+       adp8870_set_bits(client, ADP8870_MDCR, NSTBY);
+
+       return 0;
+}
+#else
+#define adp8870_i2c_suspend NULL
+#define adp8870_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id adp8870_id[] = {
+       { "adp8870", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adp8870_id);
+
+static struct i2c_driver adp8870_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+       },
+       .probe    = adp8870_probe,
+       .remove   = __devexit_p(adp8870_remove),
+       .suspend = adp8870_i2c_suspend,
+       .resume  = adp8870_i2c_resume,
+       .id_table = adp8870_id,
+};
+
+static int __init adp8870_init(void)
+{
+       return i2c_add_driver(&adp8870_driver);
+}
+module_init(adp8870_init);
+
+static void __exit adp8870_exit(void)
+{
+       i2c_del_driver(&adp8870_driver);
+}
+module_exit(adp8870_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("ADP8870 Backlight driver");
+MODULE_ALIAS("platform:adp8870-backlight");
index 00d615d7aa216d52387e8d67952851a42802a326..979d6eed9a0ff5178657ad5a36a1f203b87814b2 100644 (file)
@@ -42,7 +42,7 @@ config W1_MASTER_MXC
 
 config W1_MASTER_DS1WM
        tristate "Maxim DS1WM 1-wire busmaster"
-       depends on W1
+       depends on W1 && GENERIC_HARDIRQS
        help
          Say Y here to enable the DS1WM 1-wire driver, such as that
          in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
index e9b8e5926befb7b38b03218ffd0f9e6d2d75d454..76bff2bff15e346532be60dc1ce1a13aff070471 100644 (file)
@@ -88,7 +88,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
        pmd_t pmd = *pmdp;
        pmd_clear(mm, address, pmdp);
        return pmd;
-})
+}
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 #endif
 
diff --git a/include/linux/i2c/adp8870.h b/include/linux/i2c/adp8870.h
new file mode 100644 (file)
index 0000000..624dcec
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Definitions and platform data for Analog Devices
+ * Backlight drivers ADP8870
+ *
+ * Copyright 2009-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __LINUX_I2C_ADP8870_H
+#define __LINUX_I2C_ADP8870_H
+
+#define ID_ADP8870             8870
+
+#define ADP8870_MAX_BRIGHTNESS 0x7F
+#define FLAG_OFFT_SHIFT 8
+
+/*
+ * LEDs subdevice platform data
+ */
+
+#define ADP8870_LED_DIS_BLINK  (0 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_600ms (1 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_1200ms        (2 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_1800ms        (3 << FLAG_OFFT_SHIFT)
+
+#define ADP8870_LED_ONT_200ms  0
+#define ADP8870_LED_ONT_600ms  1
+#define ADP8870_LED_ONT_800ms  2
+#define ADP8870_LED_ONT_1200ms 3
+
+#define ADP8870_LED_D7         (7)
+#define ADP8870_LED_D6         (6)
+#define ADP8870_LED_D5         (5)
+#define ADP8870_LED_D4         (4)
+#define ADP8870_LED_D3         (3)
+#define ADP8870_LED_D2         (2)
+#define ADP8870_LED_D1         (1)
+
+/*
+ * Backlight subdevice platform data
+ */
+
+#define ADP8870_BL_D7          (1 << 6)
+#define ADP8870_BL_D6          (1 << 5)
+#define ADP8870_BL_D5          (1 << 4)
+#define ADP8870_BL_D4          (1 << 3)
+#define ADP8870_BL_D3          (1 << 2)
+#define ADP8870_BL_D2          (1 << 1)
+#define ADP8870_BL_D1          (1 << 0)
+
+#define ADP8870_FADE_T_DIS     0       /* Fade Timer Disabled */
+#define ADP8870_FADE_T_300ms   1       /* 0.3 Sec */
+#define ADP8870_FADE_T_600ms   2
+#define ADP8870_FADE_T_900ms   3
+#define ADP8870_FADE_T_1200ms  4
+#define ADP8870_FADE_T_1500ms  5
+#define ADP8870_FADE_T_1800ms  6
+#define ADP8870_FADE_T_2100ms  7
+#define ADP8870_FADE_T_2400ms  8
+#define ADP8870_FADE_T_2700ms  9
+#define ADP8870_FADE_T_3000ms  10
+#define ADP8870_FADE_T_3500ms  11
+#define ADP8870_FADE_T_4000ms  12
+#define ADP8870_FADE_T_4500ms  13
+#define ADP8870_FADE_T_5000ms  14
+#define ADP8870_FADE_T_5500ms  15      /* 5.5 Sec */
+
+#define ADP8870_FADE_LAW_LINEAR        0
+#define ADP8870_FADE_LAW_SQUARE        1
+#define ADP8870_FADE_LAW_CUBIC1        2
+#define ADP8870_FADE_LAW_CUBIC2        3
+
+#define ADP8870_BL_AMBL_FILT_80ms      0       /* Light sensor filter time */
+#define ADP8870_BL_AMBL_FILT_160ms     1
+#define ADP8870_BL_AMBL_FILT_320ms     2
+#define ADP8870_BL_AMBL_FILT_640ms     3
+#define ADP8870_BL_AMBL_FILT_1280ms    4
+#define ADP8870_BL_AMBL_FILT_2560ms    5
+#define ADP8870_BL_AMBL_FILT_5120ms    6
+#define ADP8870_BL_AMBL_FILT_10240ms   7       /* 10.24 sec */
+
+/*
+ * Blacklight current 0..30mA
+ */
+#define ADP8870_BL_CUR_mA(I)           ((I * 127) / 30)
+
+/*
+ * L2 comparator current 0..1106uA
+ */
+#define ADP8870_L2_COMP_CURR_uA(I)     ((I * 255) / 1106)
+
+/*
+ * L3 comparator current 0..551uA
+ */
+#define ADP8870_L3_COMP_CURR_uA(I)     ((I * 255) / 551)
+
+/*
+ * L4 comparator current 0..275uA
+ */
+#define ADP8870_L4_COMP_CURR_uA(I)     ((I * 255) / 275)
+
+/*
+ * L5 comparator current 0..138uA
+ */
+#define ADP8870_L5_COMP_CURR_uA(I)     ((I * 255) / 138)
+
+struct adp8870_backlight_platform_data {
+       u8 bl_led_assign;       /* 1 = Backlight 0 = Individual LED */
+       u8 pwm_assign;          /* 1 = Enables PWM mode */
+
+       u8 bl_fade_in;          /* Backlight Fade-In Timer */
+       u8 bl_fade_out;         /* Backlight Fade-Out Timer */
+       u8 bl_fade_law;         /* fade-on/fade-off transfer characteristic */
+
+       u8 en_ambl_sens;        /* 1 = enable ambient light sensor */
+       u8 abml_filt;           /* Light sensor filter time */
+
+       u8 l1_daylight_max;     /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l1_daylight_dim;     /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l2_bright_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l2_bright_dim;       /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l3_office_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l3_office_dim;       /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l4_indoor_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l4_indor_dim;        /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l5_dark_max;         /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l5_dark_dim;         /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+
+       u8 l2_trip;             /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+       u8 l2_hyst;             /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+       u8 l3_trip;             /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+       u8 l3_hyst;             /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+       u8 l4_trip;             /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+       u8 l4_hyst;             /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+       u8 l5_trip;             /* use L5_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+       u8 l5_hyst;             /* use L6_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+
+       /**
+        * Independent Current Sinks / LEDS
+        * Sinks not assigned to the Backlight can be exposed to
+        * user space using the LEDS CLASS interface
+        */
+
+       int num_leds;
+       struct led_info *leds;
+       u8 led_fade_in;         /* LED Fade-In Timer */
+       u8 led_fade_out;        /* LED Fade-Out Timer */
+       u8 led_fade_law;        /* fade-on/fade-off transfer characteristic */
+       u8 led_on_time;
+};
+
+#endif /* __LINUX_I2C_ADP8870_H */
index fb0e7329fee1a5ad370b2e5284ceb681670c7395..953352a88336c0385e2e385f93e41c278513be7b 100644 (file)
@@ -671,8 +671,8 @@ struct sysinfo {
 
 #ifdef __CHECKER__
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
-#define BUILD_BUG_ON_ZERO(e)
-#define BUILD_BUG_ON_NULL(e)
+#define BUILD_BUG_ON_ZERO(e) (0)
+#define BUILD_BUG_ON_NULL(e) ((void*)0)
 #define BUILD_BUG_ON(condition)
 #else /* __CHECKER__ */
 
index 2a0d7d651dc34f98daff0d111c5e458339006945..ee0c952188de2c99281fd7567f701893e90a47dd 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _LINUX_KMSG_DUMP_H
 #define _LINUX_KMSG_DUMP_H
 
+#include <linux/errno.h>
 #include <linux/list.h>
 
 enum kmsg_dump_reason {
index 9724a38ee69d5c9e292aa75c8fcc092486ebdbe7..50940da6adf36d7a544c32448b6873f83cef2224 100644 (file)
@@ -84,6 +84,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
 extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
+extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm);
 
 static inline
 int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
@@ -246,6 +247,11 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
        return NULL;
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
+{
+       return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
        return 1;
index 384eb5fe530b8e90c44c9f65ebb719f965cf65df..e70564647039fdcbdf5516aa9f8a9ed1cffd4d6d 100644 (file)
@@ -358,6 +358,7 @@ struct backing_dev_info;
 extern struct mm_struct *swap_token_mm;
 extern void grab_swap_token(struct mm_struct *);
 extern void __put_swap_token(struct mm_struct *);
+extern void disable_swap_token(struct mem_cgroup *memcg);
 
 static inline int has_swap_token(struct mm_struct *mm)
 {
@@ -370,11 +371,6 @@ static inline void put_swap_token(struct mm_struct *mm)
                __put_swap_token(mm);
 }
 
-static inline void disable_swap_token(void)
-{
-       put_swap_token(swap_token_mm);
-}
-
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 extern void
 mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout);
@@ -500,7 +496,7 @@ static inline int has_swap_token(struct mm_struct *mm)
        return 0;
 }
 
-static inline void disable_swap_token(void)
+static inline void disable_swap_token(struct mem_cgroup *memcg)
 {
 }
 
index b91a40e847d236d9046dc3154a7e7a58ea594776..fc839bfa7935aff66380a22e9b95589127ec66d2 100644 (file)
@@ -60,7 +60,7 @@ int arch_update_cpu_topology(void);
  * (in whatever arch specific measurement units returned by node_distance())
  * then switch on zone reclaim on boot.
  */
-#define RECLAIM_DISTANCE 20
+#define RECLAIM_DISTANCE 30
 #endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS     (1)
index 73eb1ed36ec4cdb19b92a33b146b632ac9378f38..6ddbd86377dec3375549f2f02ef5c7c47fa9bfb3 100644 (file)
@@ -9,7 +9,7 @@
 #endif
 
 #ifndef UTS_NODENAME
-#define UTS_NODENAME "(none)"  /* set by sethostname() */
+#define UTS_NODENAME CONFIG_DEFAULT_HOSTNAME /* set by sethostname() */
 #endif
 
 #ifndef UTS_DOMAINNAME
index ea422aaa23e12a2397e08a167e36dd65ce7041cf..b2c33bd955faa4536082e62e6c9f17946994afde 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <linux/types.h>
 #include <linux/tracepoint.h>
+#include <linux/mm.h>
+#include <linux/memcontrol.h>
 #include "gfpflags.h"
 
 #define RECLAIM_WB_ANON                0x0001u
@@ -310,6 +312,87 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
                show_reclaim_flags(__entry->reclaim_flags))
 );
 
+TRACE_EVENT(replace_swap_token,
+       TP_PROTO(struct mm_struct *old_mm,
+                struct mm_struct *new_mm),
+
+       TP_ARGS(old_mm, new_mm),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*,      old_mm)
+               __field(unsigned int,           old_prio)
+               __field(struct mm_struct*,      new_mm)
+               __field(unsigned int,           new_prio)
+       ),
+
+       TP_fast_assign(
+               __entry->old_mm   = old_mm;
+               __entry->old_prio = old_mm ? old_mm->token_priority : 0;
+               __entry->new_mm   = new_mm;
+               __entry->new_prio = new_mm->token_priority;
+       ),
+
+       TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u",
+                 __entry->old_mm, __entry->old_prio,
+                 __entry->new_mm, __entry->new_prio)
+);
+
+DECLARE_EVENT_CLASS(put_swap_token_template,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+
+       TP_ARGS(swap_token_mm),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*, swap_token_mm)
+       ),
+
+       TP_fast_assign(
+               __entry->swap_token_mm = swap_token_mm;
+       ),
+
+       TP_printk("token_mm=%p", __entry->swap_token_mm)
+);
+
+DEFINE_EVENT(put_swap_token_template, put_swap_token,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+       TP_ARGS(swap_token_mm)
+);
+
+DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+       TP_ARGS(swap_token_mm),
+       TP_CONDITION(swap_token_mm != NULL)
+);
+
+TRACE_EVENT_CONDITION(update_swap_token_priority,
+       TP_PROTO(struct mm_struct *mm,
+                unsigned int old_prio,
+                struct mm_struct *swap_token_mm),
+
+       TP_ARGS(mm, old_prio, swap_token_mm),
+
+       TP_CONDITION(mm->token_priority != old_prio),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*, mm)
+               __field(unsigned int, old_prio)
+               __field(unsigned int, new_prio)
+               __field(struct mm_struct*, swap_token_mm)
+               __field(unsigned int, swap_token_prio)
+       ),
+
+       TP_fast_assign(
+               __entry->mm             = mm;
+               __entry->old_prio       = old_prio;
+               __entry->new_prio       = mm->token_priority;
+               __entry->swap_token_mm  = swap_token_mm;
+               __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0;
+       ),
+
+       TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u",
+                 __entry->mm, __entry->old_prio, __entry->new_prio,
+                 __entry->swap_token_mm, __entry->swap_token_prio)
+);
 
 #endif /* _TRACE_VMSCAN_H */
 
index ebafac4231eeff15883809419e6df0c211b90e1a..412c21b00d513f81269d7860b1a9af1909e0225f 100644 (file)
@@ -19,7 +19,6 @@ config DEFCONFIG_LIST
 config CONSTRUCTORS
        bool
        depends on !UML
-       default y
 
 config HAVE_IRQ_WORK
        bool
@@ -204,6 +203,15 @@ config KERNEL_LZO
 
 endchoice
 
+config DEFAULT_HOSTNAME
+       string "Default hostname"
+       default "(none)"
+       help
+         This option determines the default system hostname before userspace
+         calls sethostname(2). The kernel traditionally uses "(none)" here,
+         but you may wish to use a different default here to make a minimal
+         system more usable with less configuration.
+
 config SWAP
        bool "Support for paging of anonymous memory (swap)"
        depends on MMU && BLOCK
index cfd7000c9d7108085b337876893fa6e91910dc04..2568d22a304ecc667b302b0b5d17956ed6d143a8 100644 (file)
@@ -93,9 +93,6 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
                 * If the upper limit and lower limit of the timer_rate is
                 * >= 12.5% apart, redo calibration.
                 */
-               printk(KERN_DEBUG "calibrate_delay_direct() timer_rate_max=%lu "
-                           "timer_rate_min=%lu pre_start=%lu pre_end=%lu\n",
-                         timer_rate_max, timer_rate_min, pre_start, pre_end);
                if (start >= post_end)
                        printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
                                        "timer_rate as we had a TSC wrap around"
index 20a406471525af2087cf914d8569d401306b3a5b..f2b321bae44037c08d4b09b90b8610a80b979eb7 100644 (file)
@@ -561,29 +561,28 @@ void exit_files(struct task_struct *tsk)
 
 #ifdef CONFIG_MM_OWNER
 /*
- * Task p is exiting and it owned mm, lets find a new owner for it
+ * A task is exiting.   If it owned this mm, find a new owner for the mm.
  */
-static inline int
-mm_need_new_owner(struct mm_struct *mm, struct task_struct *p)
-{
-       /*
-        * If there are other users of the mm and the owner (us) is exiting
-        * we need to find a new owner to take on the responsibility.
-        */
-       if (atomic_read(&mm->mm_users) <= 1)
-               return 0;
-       if (mm->owner != p)
-               return 0;
-       return 1;
-}
-
 void mm_update_next_owner(struct mm_struct *mm)
 {
        struct task_struct *c, *g, *p = current;
 
 retry:
-       if (!mm_need_new_owner(mm, p))
+       /*
+        * If the exiting or execing task is not the owner, it's
+        * someone else's problem.
+        */
+       if (mm->owner != p)
                return;
+       /*
+        * The current owner is exiting/execing and there are no other
+        * candidates.  Do not leave the mm pointing to a possibly
+        * freed task structure.
+        */
+       if (atomic_read(&mm->mm_users) <= 1) {
+               mm->owner = NULL;
+               return;
+       }
 
        read_lock(&tasklist_lock);
        /*
index b8cadf70b1fbd109c4ca56f78f6f9a685e2f9974..5bf924d80b5c64be2888be0afd65008260e8db01 100644 (file)
@@ -2,7 +2,8 @@ menu "GCOV-based kernel profiling"
 
 config GCOV_KERNEL
        bool "Enable gcov-based kernel profiling"
-       depends on DEBUG_FS && CONSTRUCTORS
+       depends on DEBUG_FS
+       select CONSTRUCTORS
        default n
        ---help---
        This option enables gcov-based code profiling (e.g. for code coverage
index 88725c939e0b8000253905332db8725507781f48..10d018212bab8b1ad2f53e1ed388a4bbd56d4656 100644 (file)
@@ -1096,7 +1096,7 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag
         * to move current somewhere else, making room for our non-migratable
         * task.
         */
-       if (p->prio == rq->curr->prio && !need_resched())
+       if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr))
                check_preempt_equal_prio(rq, p);
 #endif
 }
@@ -1239,6 +1239,10 @@ static int find_lowest_rq(struct task_struct *task)
        int this_cpu = smp_processor_id();
        int cpu      = task_cpu(task);
 
+       /* Make sure the mask is initialized first */
+       if (unlikely(!lowest_mask))
+               return -1;
+
        if (task->rt.nr_cpus_allowed == 1)
                return -1; /* No other targets possible */
 
index 86c32b884f8efbb8f071b6343b3c37667b4e8fa3..ff7678603328b3ba5e00c74dc9fd08bcbf113987 100644 (file)
@@ -2365,7 +2365,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
 /**
  *  sys_rt_sigprocmask - change the list of currently blocked signals
  *  @how: whether to add, remove, or set signals
- *  @set: stores pending signals
+ *  @nset: stores pending signals
  *  @oset: previous value of signal mask if non-null
  *  @sigsetsize: size of sigset_t type
  */
index 41baf02924e64cc926ef3b2560a8f02c76c1bbf0..3f3b68199d744bd4fc9b94dcb9ca6e831502b0f2 100644 (file)
@@ -572,7 +572,7 @@ EXPORT_SYMBOL(bitmap_scnlistprintf);
 
 /**
  * __bitmap_parselist - convert list format ASCII string to bitmap
- * @bp: read nul-terminated user string from this buffer
+ * @buf: read nul-terminated user string from this buffer
  * @buflen: buffer size in bytes.  If string is smaller than this
  *    then it must be terminated with a \0.
  * @is_user: location of buffer, 0 indicates kernel space
index 021a2960ef9e18d061c972590f7651a35e7652ce..6cc604bd56496e2742e371d63234af08f9f0859b 100644 (file)
@@ -144,9 +144,20 @@ static void isolate_freepages(struct zone *zone,
        int nr_freepages = cc->nr_freepages;
        struct list_head *freelist = &cc->freepages;
 
+       /*
+        * Initialise the free scanner. The starting point is where we last
+        * scanned from (or the end of the zone if starting). The low point
+        * is the end of the pageblock the migration scanner is using.
+        */
        pfn = cc->free_pfn;
        low_pfn = cc->migrate_pfn + pageblock_nr_pages;
-       high_pfn = low_pfn;
+
+       /*
+        * Take care that if the migration scanner is at the end of the zone
+        * that the free scanner does not accidentally move to the next zone
+        * in the next isolation cycle.
+        */
+       high_pfn = min(low_pfn, pfn);
 
        /*
         * Isolate free pages until enough are available to migrate the
@@ -240,11 +251,18 @@ static bool too_many_isolated(struct zone *zone)
        return isolated > (inactive + active) / 2;
 }
 
+/* possible outcome of isolate_migratepages */
+typedef enum {
+       ISOLATE_ABORT,          /* Abort compaction now */
+       ISOLATE_NONE,           /* No pages isolated, continue scanning */
+       ISOLATE_SUCCESS,        /* Pages isolated, migrate */
+} isolate_migrate_t;
+
 /*
  * Isolate all pages that can be migrated from the block pointed to by
  * the migrate scanner within compact_control.
  */
-static unsigned long isolate_migratepages(struct zone *zone,
+static isolate_migrate_t isolate_migratepages(struct zone *zone,
                                        struct compact_control *cc)
 {
        unsigned long low_pfn, end_pfn;
@@ -261,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
        /* Do not cross the free scanner or scan within a memory hole */
        if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
                cc->migrate_pfn = end_pfn;
-               return 0;
+               return ISOLATE_NONE;
        }
 
        /*
@@ -270,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone,
         * delay for some time until fewer pages are isolated
         */
        while (unlikely(too_many_isolated(zone))) {
+               /* async migration should just abort */
+               if (!cc->sync)
+                       return ISOLATE_ABORT;
+
                congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                if (fatal_signal_pending(current))
-                       return 0;
+                       return ISOLATE_ABORT;
        }
 
        /* Time to isolate some pages for migration */
@@ -358,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
 
        trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
 
-       return cc->nr_migratepages;
+       return ISOLATE_SUCCESS;
 }
 
 /*
@@ -420,13 +442,6 @@ static int compact_finished(struct zone *zone,
        if (cc->free_pfn <= cc->migrate_pfn)
                return COMPACT_COMPLETE;
 
-       /* Compaction run is not finished if the watermark is not met */
-       watermark = low_wmark_pages(zone);
-       watermark += (1 << cc->order);
-
-       if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
-               return COMPACT_CONTINUE;
-
        /*
         * order == -1 is expected when compacting via
         * /proc/sys/vm/compact_memory
@@ -434,6 +449,13 @@ static int compact_finished(struct zone *zone,
        if (cc->order == -1)
                return COMPACT_CONTINUE;
 
+       /* Compaction run is not finished if the watermark is not met */
+       watermark = low_wmark_pages(zone);
+       watermark += (1 << cc->order);
+
+       if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
+               return COMPACT_CONTINUE;
+
        /* Direct compactor: Is a suitable page free? */
        for (order = cc->order; order < MAX_ORDER; order++) {
                /* Job done if page is free of the right migratetype */
@@ -460,6 +482,13 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        int fragindex;
        unsigned long watermark;
 
+       /*
+        * order == -1 is expected when compacting via
+        * /proc/sys/vm/compact_memory
+        */
+       if (order == -1)
+               return COMPACT_CONTINUE;
+
        /*
         * Watermarks for order-0 must be met for compaction. Note the 2UL.
         * This is because during migration, copies of pages need to be
@@ -469,18 +498,12 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
                return COMPACT_SKIPPED;
 
-       /*
-        * order == -1 is expected when compacting via
-        * /proc/sys/vm/compact_memory
-        */
-       if (order == -1)
-               return COMPACT_CONTINUE;
-
        /*
         * fragmentation index determines if allocation failures are due to
         * low memory or external fragmentation
         *
-        * index of -1 implies allocations might succeed dependingon watermarks
+        * index of -1000 implies allocations might succeed depending on
+        * watermarks
         * index towards 0 implies failure is due to lack of memory
         * index towards 1000 implies failure is due to fragmentation
         *
@@ -490,7 +513,8 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
                return COMPACT_SKIPPED;
 
-       if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0))
+       if (fragindex == -1000 && zone_watermark_ok(zone, order, watermark,
+           0, 0))
                return COMPACT_PARTIAL;
 
        return COMPACT_CONTINUE;
@@ -522,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                unsigned long nr_migrate, nr_remaining;
                int err;
 
-               if (!isolate_migratepages(zone, cc))
+               switch (isolate_migratepages(zone, cc)) {
+               case ISOLATE_ABORT:
+                       ret = COMPACT_PARTIAL;
+                       goto out;
+               case ISOLATE_NONE:
                        continue;
+               case ISOLATE_SUCCESS:
+                       ;
+               }
 
                nr_migrate = cc->nr_migratepages;
                err = migrate_pages(&cc->migratepages, compaction_alloc,
@@ -547,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 
        }
 
+out:
        /* Release free pages and check accounting */
        cc->nr_freepages -= release_freepages(&cc->freepages);
        VM_BUG_ON(cc->nr_freepages != 0);
index 615d9743a3cbad1ca19d745c45115eecb1c463f4..81532f297fd22cd11e1c7a4161c8e320a7015ec2 100644 (file)
@@ -2234,11 +2234,8 @@ static void khugepaged_loop(void)
        while (likely(khugepaged_enabled())) {
 #ifndef CONFIG_NUMA
                hpage = khugepaged_alloc_hugepage();
-               if (unlikely(!hpage)) {
-                       count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
+               if (unlikely(!hpage))
                        break;
-               }
-               count_vm_event(THP_COLLAPSE_ALLOC);
 #else
                if (IS_ERR(hpage)) {
                        khugepaged_alloc_sleep();
index 6402458fee38ca5ba2109882e92ebbf63e97c787..bfcf153bc82907f31ccc1921256622a82bf20d2f 100644 (file)
@@ -1111,6 +1111,14 @@ static void __init gather_bootmem_prealloc(void)
                WARN_ON(page_count(page) != 1);
                prep_compound_huge_page(page, h->order);
                prep_new_huge_page(h, page, page_to_nid(page));
+               /*
+                * If we had gigantic hugepages allocated at boot time, we need
+                * to restore the 'stolen' pages to totalram_pages in order to
+                * fix confusing memory reports from free(1) and another
+                * side-effects, like CommitLimit going negative.
+                */
+               if (h->order > (MAX_ORDER - 1))
+                       totalram_pages += 1 << h->order;
        }
 }
 
index d708b3ef2260282a3d6e5784a60c1fb003339f8e..9a68b0cf0a1c4c8009ee25d2990530d7e2927132 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
                slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list);
                ksm_scan.mm_slot = slot;
                spin_unlock(&ksm_mmlist_lock);
+               /*
+                * Although we tested list_empty() above, a racing __ksm_exit
+                * of the last mm on the list may have removed it since then.
+                */
+               if (slot == &ksm_mm_head)
+                       return NULL;
 next_mm:
                ksm_scan.address = 0;
                ksm_scan.rmap_list = &slot->rmap_list;
index bd9052a5d3ad74aa2db023c953f0b498e5ab7dd0..cf7d027a8844b115bcc6d213264707d220c6c3d9 100644 (file)
@@ -359,7 +359,7 @@ enum charge_type {
 static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
-static void drain_all_stock_async(void);
+static void drain_all_stock_async(struct mem_cgroup *mem);
 
 static struct mem_cgroup_per_zone *
 mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
@@ -735,7 +735,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
                                struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
+struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 {
        struct mem_cgroup *mem = NULL;
 
@@ -1663,15 +1663,21 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
        excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
 
        /* If memsw_is_minimum==1, swap-out is of-no-use. */
-       if (root_mem->memsw_is_minimum)
+       if (!check_soft && root_mem->memsw_is_minimum)
                noswap = true;
 
        while (1) {
                victim = mem_cgroup_select_victim(root_mem);
                if (victim == root_mem) {
                        loop++;
-                       if (loop >= 1)
-                               drain_all_stock_async();
+                       /*
+                        * We are not draining per cpu cached charges during
+                        * soft limit reclaim  because global reclaim doesn't
+                        * care about charges. It tries to free some memory and
+                        * charges will not give any.
+                        */
+                       if (!check_soft && loop >= 1)
+                               drain_all_stock_async(root_mem);
                        if (loop >= 2) {
                                /*
                                 * If we have not been able to reclaim
@@ -1934,9 +1940,11 @@ struct memcg_stock_pcp {
        struct mem_cgroup *cached; /* this never be root cgroup */
        unsigned int nr_pages;
        struct work_struct work;
+       unsigned long flags;
+#define FLUSHING_CACHED_CHARGE (0)
 };
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
-static atomic_t memcg_drain_count;
+static DEFINE_MUTEX(percpu_charge_mutex);
 
 /*
  * Try to consume stocked charge on this cpu. If success, one page is consumed
@@ -1984,6 +1992,7 @@ static void drain_local_stock(struct work_struct *dummy)
 {
        struct memcg_stock_pcp *stock = &__get_cpu_var(memcg_stock);
        drain_stock(stock);
+       clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags);
 }
 
 /*
@@ -2008,26 +2017,45 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages)
  * expects some charges will be back to res_counter later but cannot wait for
  * it.
  */
-static void drain_all_stock_async(void)
+static void drain_all_stock_async(struct mem_cgroup *root_mem)
 {
-       int cpu;
-       /* This function is for scheduling "drain" in asynchronous way.
-        * The result of "drain" is not directly handled by callers. Then,
-        * if someone is calling drain, we don't have to call drain more.
-        * Anyway, WORK_STRUCT_PENDING check in queue_work_on() will catch if
-        * there is a race. We just do loose check here.
+       int cpu, curcpu;
+       /*
+        * If someone calls draining, avoid adding more kworker runs.
         */
-       if (atomic_read(&memcg_drain_count))
+       if (!mutex_trylock(&percpu_charge_mutex))
                return;
        /* Notify other cpus that system-wide "drain" is running */
-       atomic_inc(&memcg_drain_count);
        get_online_cpus();
+       /*
+        * Get a hint for avoiding draining charges on the current cpu,
+        * which must be exhausted by our charging.  It is not required that
+        * this be a precise check, so we use raw_smp_processor_id() instead of
+        * getcpu()/putcpu().
+        */
+       curcpu = raw_smp_processor_id();
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
-               schedule_work_on(cpu, &stock->work);
+               struct mem_cgroup *mem;
+
+               if (cpu == curcpu)
+                       continue;
+
+               mem = stock->cached;
+               if (!mem)
+                       continue;
+               if (mem != root_mem) {
+                       if (!root_mem->use_hierarchy)
+                               continue;
+                       /* check whether "mem" is under tree of "root_mem" */
+                       if (!css_is_ancestor(&mem->css, &root_mem->css))
+                               continue;
+               }
+               if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
+                       schedule_work_on(cpu, &stock->work);
        }
        put_online_cpus();
-       atomic_dec(&memcg_drain_count);
+       mutex_unlock(&percpu_charge_mutex);
        /* We don't wait for flush_work */
 }
 
@@ -2035,9 +2063,9 @@ static void drain_all_stock_async(void)
 static void drain_all_stock_sync(void)
 {
        /* called when force_empty is called */
-       atomic_inc(&memcg_drain_count);
+       mutex_lock(&percpu_charge_mutex);
        schedule_on_each_cpu(drain_local_stock);
-       atomic_dec(&memcg_drain_count);
+       mutex_unlock(&percpu_charge_mutex);
 }
 
 /*
@@ -4640,6 +4668,7 @@ static struct cftype mem_cgroup_files[] = {
        {
                .name = "numa_stat",
                .open = mem_control_numa_stat_open,
+               .mode = S_IRUGO,
        },
 #endif
 };
@@ -5414,18 +5443,16 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
                                struct cgroup *old_cont,
                                struct task_struct *p)
 {
-       struct mm_struct *mm;
+       struct mm_struct *mm = get_task_mm(p);
 
-       if (!mc.to)
-               /* no need to move charge */
-               return;
-
-       mm = get_task_mm(p);
        if (mm) {
-               mem_cgroup_move_charge(mm);
+               if (mc.to)
+                       mem_cgroup_move_charge(mm);
+               put_swap_token(mm);
                mmput(mm);
        }
-       mem_cgroup_clear_mc();
+       if (mc.to)
+               mem_cgroup_clear_mc();
 }
 #else  /* !CONFIG_MMU */
 static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
index 5c8f7e08928d5faba209a0392b4b2befe17a67e3..eac0ba5614912e57c7b83b22382bc1165138ef2a 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/swapops.h>
 #include <linux/hugetlb.h>
 #include <linux/memory_hotplug.h>
+#include <linux/mm_inline.h>
 #include "internal.h"
 
 int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -1468,7 +1469,8 @@ int soft_offline_page(struct page *page, int flags)
        put_page(page);
        if (!ret) {
                LIST_HEAD(pagelist);
-
+               inc_zone_page_state(page, NR_ISOLATED_ANON +
+                                           page_is_file_cache(page));
                list_add(&page->lru, &pagelist);
                ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL,
                                                                0, true);
index 6953d3926e01e8ad1370304064ec2a0e94ad1ebb..87d935333f0dda3d477c5cacd1219b78e7b910e7 100644 (file)
@@ -1112,11 +1112,13 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
        int force_flush = 0;
        int rss[NR_MM_COUNTERS];
        spinlock_t *ptl;
+       pte_t *start_pte;
        pte_t *pte;
 
 again:
        init_rss_vec(rss);
-       pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       pte = start_pte;
        arch_enter_lazy_mmu_mode();
        do {
                pte_t ptent = *pte;
@@ -1196,7 +1198,7 @@ again:
 
        add_mm_rss_vec(mm, rss);
        arch_leave_lazy_mmu_mode();
-       pte_unmap_unlock(pte - 1, ptl);
+       pte_unmap_unlock(start_pte, ptl);
 
        /*
         * mmu_gather ran out of room to batch pages, we break out of
@@ -1296,7 +1298,7 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb,
 
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
- * @tlbp: address of the caller's struct mmu_gather
+ * @tlb: address of the caller's struct mmu_gather
  * @vma: the starting vma
  * @start_addr: virtual address at which to start unmapping
  * @end_addr: virtual address at which to end unmapping
index 9f646374e32f5ec7704b86ad653c2794037b830a..02159c755136ea0463f57a2a951f9cad223aceb1 100644 (file)
@@ -494,6 +494,12 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
        /* init node's zones as empty zones, we don't have any present pages.*/
        free_area_init_node(nid, zones_size, start_pfn, zholes_size);
 
+       /*
+        * The node we allocated has no zone fallback lists. For avoiding
+        * to access not-initialized zonelist, build here.
+        */
+       build_all_zonelists(NULL);
+
        return pgdat;
 }
 
index bbdc9af5e1177108894d881126761fa71ef9cada..d49736ff8a8dad10420a4f2f76ca89da52c7da89 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -906,14 +906,7 @@ struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma)
        if (anon_vma)
                return anon_vma;
 try_prev:
-       /*
-        * It is potentially slow to have to call find_vma_prev here.
-        * But it's only on the first write fault on the vma, not
-        * every time, and we could devise a way to avoid it later
-        * (e.g. stash info in next's anon_vma_node when assigning
-        * an anon_vma, or when trying vma_merge).  Another time.
-        */
-       BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma);
+       near = vma->vm_prev;
        if (!near)
                goto none;
 
@@ -2044,9 +2037,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
                return -EINVAL;
 
        /* Find the first overlapping VMA */
-       vma = find_vma_prev(mm, start, &prev);
+       vma = find_vma(mm, start);
        if (!vma)
                return 0;
+       prev = vma->vm_prev;
        /* we have  start < vma->vm_end  */
 
        /* if it doesn't overlap, we have nothing.. */
index 74ccff61d1bea8d6e258170280ea5b20523dad23..53bffc6c293eb4fb7aa2a00be5a8712946dab5c9 100644 (file)
@@ -162,13 +162,13 @@ static void free_page_cgroup(void *addr)
 }
 #endif
 
-static int __meminit init_section_page_cgroup(unsigned long pfn)
+static int __meminit init_section_page_cgroup(unsigned long pfn, int nid)
 {
        struct page_cgroup *base, *pc;
        struct mem_section *section;
        unsigned long table_size;
        unsigned long nr;
-       int nid, index;
+       int index;
 
        nr = pfn_to_section_nr(pfn);
        section = __nr_to_section(nr);
@@ -176,7 +176,6 @@ static int __meminit init_section_page_cgroup(unsigned long pfn)
        if (section->page_cgroup)
                return 0;
 
-       nid = page_to_nid(pfn_to_page(pfn));
        table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
        base = alloc_page_cgroup(table_size, nid);
 
@@ -196,7 +195,11 @@ static int __meminit init_section_page_cgroup(unsigned long pfn)
                pc = base + index;
                init_page_cgroup(pc, nr);
        }
-
+       /*
+        * The passed "pfn" may not be aligned to SECTION.  For the calculation
+        * we need to apply a mask.
+        */
+       pfn &= PAGE_SECTION_MASK;
        section->page_cgroup = base - pfn;
        total_usage += table_size;
        return 0;
@@ -225,10 +228,20 @@ int __meminit online_page_cgroup(unsigned long start_pfn,
        start = start_pfn & ~(PAGES_PER_SECTION - 1);
        end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
 
+       if (nid == -1) {
+               /*
+                * In this case, "nid" already exists and contains valid memory.
+                * "start_pfn" passed to us is a pfn which is an arg for
+                * online__pages(), and start_pfn should exist.
+                */
+               nid = pfn_to_nid(start_pfn);
+               VM_BUG_ON(!node_state(nid, N_ONLINE));
+       }
+
        for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) {
                if (!pfn_present(pfn))
                        continue;
-               fail = init_section_page_cgroup(pfn);
+               fail = init_section_page_cgroup(pfn, nid);
        }
        if (!fail)
                return 0;
@@ -284,25 +297,47 @@ static int __meminit page_cgroup_callback(struct notifier_block *self,
 void __init page_cgroup_init(void)
 {
        unsigned long pfn;
-       int fail = 0;
+       int nid;
 
        if (mem_cgroup_disabled())
                return;
 
-       for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
-               if (!pfn_present(pfn))
-                       continue;
-               fail = init_section_page_cgroup(pfn);
-       }
-       if (fail) {
-               printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n");
-               panic("Out of memory");
-       } else {
-               hotplug_memory_notifier(page_cgroup_callback, 0);
+       for_each_node_state(nid, N_HIGH_MEMORY) {
+               unsigned long start_pfn, end_pfn;
+
+               start_pfn = node_start_pfn(nid);
+               end_pfn = node_end_pfn(nid);
+               /*
+                * start_pfn and end_pfn may not be aligned to SECTION and the
+                * page->flags of out of node pages are not initialized.  So we
+                * scan [start_pfn, the biggest section's pfn < end_pfn) here.
+                */
+               for (pfn = start_pfn;
+                    pfn < end_pfn;
+                     pfn = ALIGN(pfn + 1, PAGES_PER_SECTION)) {
+
+                       if (!pfn_valid(pfn))
+                               continue;
+                       /*
+                        * Nodes's pfns can be overlapping.
+                        * We know some arch can have a nodes layout such as
+                        * -------------pfn-------------->
+                        * N0 | N1 | N2 | N0 | N1 | N2|....
+                        */
+                       if (pfn_to_nid(pfn) != nid)
+                               continue;
+                       if (init_section_page_cgroup(pfn, nid))
+                               goto oom;
+               }
        }
+       hotplug_memory_notifier(page_cgroup_callback, 0);
        printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage);
-       printk(KERN_INFO "please try 'cgroup_disable=memory' option if you don't"
-       " want memory cgroups\n");
+       printk(KERN_INFO "please try 'cgroup_disable=memory' option if you "
+                        "don't want memory cgroups\n");
+       return;
+oom:
+       printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n");
+       panic("Out of memory");
 }
 
 void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
index 2372d4ed5dd8ff763d3aaed5cb546c8033eca1ff..fabf2d0f51695eddacdb6b013fac0b9cdee3a655 100644 (file)
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
+#include <linux/memcontrol.h>
+
+#include <trace/events/vmscan.h>
+
+#define TOKEN_AGING_INTERVAL   (0xFF)
 
 static DEFINE_SPINLOCK(swap_token_lock);
 struct mm_struct *swap_token_mm;
+struct mem_cgroup *swap_token_memcg;
 static unsigned int global_faults;
+static unsigned int last_aging;
+
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
+{
+       struct mem_cgroup *memcg;
+
+       memcg = try_get_mem_cgroup_from_mm(mm);
+       if (memcg)
+               css_put(mem_cgroup_css(memcg));
+
+       return memcg;
+}
+#else
+static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
+{
+       return NULL;
+}
+#endif
 
 void grab_swap_token(struct mm_struct *mm)
 {
        int current_interval;
+       unsigned int old_prio = mm->token_priority;
 
        global_faults++;
 
@@ -38,40 +64,81 @@ void grab_swap_token(struct mm_struct *mm)
                return;
 
        /* First come first served */
-       if (swap_token_mm == NULL) {
-               mm->token_priority = mm->token_priority + 2;
-               swap_token_mm = mm;
-               goto out;
+       if (!swap_token_mm)
+               goto replace_token;
+
+       if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) {
+               swap_token_mm->token_priority /= 2;
+               last_aging = global_faults;
        }
 
-       if (mm != swap_token_mm) {
-               if (current_interval < mm->last_interval)
-                       mm->token_priority++;
-               else {
-                       if (likely(mm->token_priority > 0))
-                               mm->token_priority--;
-               }
-               /* Check if we deserve the token */
-               if (mm->token_priority > swap_token_mm->token_priority) {
-                       mm->token_priority += 2;
-                       swap_token_mm = mm;
-               }
-       } else {
-               /* Token holder came in again! */
+       if (mm == swap_token_mm) {
                mm->token_priority += 2;
+               goto update_priority;
+       }
+
+       if (current_interval < mm->last_interval)
+               mm->token_priority++;
+       else {
+               if (likely(mm->token_priority > 0))
+                       mm->token_priority--;
        }
 
+       /* Check if we deserve the token */
+       if (mm->token_priority > swap_token_mm->token_priority)
+               goto replace_token;
+
+update_priority:
+       trace_update_swap_token_priority(mm, old_prio, swap_token_mm);
+
 out:
        mm->faultstamp = global_faults;
        mm->last_interval = current_interval;
        spin_unlock(&swap_token_lock);
+       return;
+
+replace_token:
+       mm->token_priority += 2;
+       trace_replace_swap_token(swap_token_mm, mm);
+       swap_token_mm = mm;
+       swap_token_memcg = swap_token_memcg_from_mm(mm);
+       last_aging = global_faults;
+       goto out;
 }
 
 /* Called on process exit. */
 void __put_swap_token(struct mm_struct *mm)
 {
        spin_lock(&swap_token_lock);
-       if (likely(mm == swap_token_mm))
+       if (likely(mm == swap_token_mm)) {
+               trace_put_swap_token(swap_token_mm);
                swap_token_mm = NULL;
+               swap_token_memcg = NULL;
+       }
        spin_unlock(&swap_token_lock);
 }
+
+static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b)
+{
+       if (!a)
+               return true;
+       if (!b)
+               return true;
+       if (a == b)
+               return true;
+       return false;
+}
+
+void disable_swap_token(struct mem_cgroup *memcg)
+{
+       /* memcg reclaim don't disable unrelated mm token. */
+       if (match_memcg(memcg, swap_token_memcg)) {
+               spin_lock(&swap_token_lock);
+               if (match_memcg(memcg, swap_token_memcg)) {
+                       trace_disable_swap_token(swap_token_mm);
+                       swap_token_mm = NULL;
+                       swap_token_memcg = NULL;
+               }
+               spin_unlock(&swap_token_lock);
+       }
+}
index faa0a088f9cc83a5a4cd7d05e40924144c795c19..8ff834e19c2460d33844e43154b058974a6c9849 100644 (file)
@@ -1124,8 +1124,20 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                                        nr_lumpy_dirty++;
                                scan++;
                        } else {
-                               /* the page is freed already. */
-                               if (!page_count(cursor_page))
+                               /*
+                                * Check if the page is freed already.
+                                *
+                                * We can't use page_count() as that
+                                * requires compound_head and we don't
+                                * have a pin on the page here. If a
+                                * page is tail, we may or may not
+                                * have isolated the head, so assume
+                                * it's not free, it'd be tricky to
+                                * track the head status without a
+                                * page pin.
+                                */
+                               if (!PageTail(cursor_page) &&
+                                   !atomic_read(&cursor_page->_count))
                                        continue;
                                break;
                        }
@@ -2081,7 +2093,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
        for (priority = DEF_PRIORITY; priority >= 0; priority--) {
                sc->nr_scanned = 0;
                if (!priority)
-                       disable_swap_token();
+                       disable_swap_token(sc->mem_cgroup);
                total_scanned += shrink_zones(priority, zonelist, sc);
                /*
                 * Don't shrink slabs when reclaiming memory from
@@ -2407,7 +2419,7 @@ loop_again:
 
                /* The swap token gets in the way of swapout... */
                if (!priority)
-                       disable_swap_token();
+                       disable_swap_token(NULL);
 
                all_zones_ok = 1;
                balanced = 0;
index 8657f99bfb2b7d171df283d82092cba96731fcbd..b0aa2c680593d0c09857b9447d54ef933861ed3b 100755 (executable)
@@ -1943,6 +1943,11 @@ sub process {
                        WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
                }
 
+# check for uses of printk_ratelimit
+               if ($line =~ /\bprintk_ratelimit\s*\(/) {
+                       WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
+               }
+
 # printk should use KERN_* levels.  Note that follow on printk's on the
 # same line do not need a level, so we use the current block context
 # to try and find and validate the current printk.  In summary the current