[kernel] r10834 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series
Maximilian Attems
maks at alioth.debian.org
Fri Mar 14 10:05:48 UTC 2008
Author: maks
Date: Fri Mar 14 10:05:47 2008
New Revision: 10834
Log:
update to patch-2.6.25-rc5-git4
acpi merge bonus
Added:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git4
- copied, changed from r10833, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git3
Removed:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git3
Modified:
dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
Copied: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git4 (from r10833, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git3)
==============================================================================
--- /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git3 (original)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc5-git4 Fri Mar 14 10:05:47 2008
@@ -1,3 +1,2009 @@
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index 042073f..fc8e7c7 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -225,8 +225,6 @@ kprobes.txt
+ - documents the kernel probes debugging feature.
+ kref.txt
+ - docs on adding reference counters (krefs) to kernel objects.
+-laptop-mode.txt
+- - how to conserve battery power using laptop-mode.
+ laptops/
+ - directory with laptop related info and laptop driver documentation.
+ ldm.txt
+@@ -301,12 +299,8 @@ pcmcia/
+ - info on the Linux PCMCIA driver.
+ pi-futex.txt
+ - documentation on lightweight PI-futexes.
+-pm.txt
+- - info on Linux power management support.
+ pnp.txt
+ - Linux Plug and Play documentation.
+-power_supply_class.txt
+- - Tells userspace about battery, UPS, AC or DC power supply properties
+ power/
+ - directory with info on Linux PCI power management.
+ powerpc/
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index 5681e2f..518ebe6 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -1506,13 +1506,13 @@ laptop_mode
+ -----------
+
+ laptop_mode is a knob that controls "laptop mode". All the things that are
+-controlled by this knob are discussed in Documentation/laptop-mode.txt.
++controlled by this knob are discussed in Documentation/laptops/laptop-mode.txt.
+
+ block_dump
+ ----------
+
+ block_dump enables block I/O debugging when set to a nonzero value. More
+-information on block I/O debugging is in Documentation/laptop-mode.txt.
++information on block I/O debugging is in Documentation/laptops/laptop-mode.txt.
+
+ swap_token_timeout
+ ------------------
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 533e67f..49318b9 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -138,7 +138,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ strict -- Be less tolerant of platforms that are not
+ strictly ACPI specification compliant.
+
+- See also Documentation/pm.txt, pci=noacpi
++ See also Documentation/power/pm.txt, pci=noacpi
+
+ acpi_apic_instance= [ACPI, IOAPIC]
+ Format: <int>
+diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
+deleted file mode 100644
+index eeedee1..0000000
+--- a/Documentation/laptop-mode.txt
++++ /dev/null
+@@ -1,950 +0,0 @@
+-How to conserve battery power using laptop-mode
+------------------------------------------------
+-
+-Document Author: Bart Samwel (bart at samwel.tk)
+-Date created: January 2, 2004
+-Last modified: December 06, 2004
+-
+-Introduction
+-------------
+-
+-Laptop mode is used to minimize the time that the hard disk needs to be spun up,
+-to conserve battery power on laptops. It has been reported to cause significant
+-power savings.
+-
+-Contents
+---------
+-
+-* Introduction
+-* Installation
+-* Caveats
+-* The Details
+-* Tips & Tricks
+-* Control script
+-* ACPI integration
+-* Monitoring tool
+-
+-
+-Installation
+-------------
+-
+-To use laptop mode, you don't need to set any kernel configuration options
+-or anything. Simply install all the files included in this document, and
+-laptop mode will automatically be started when you're on battery. For
+-your convenience, a tarball containing an installer can be downloaded at:
+-
+-http://www.samwel.tk/laptop_mode/laptop_mode/
+-
+-To configure laptop mode, you need to edit the configuration file, which is
+-located in /etc/default/laptop-mode on Debian-based systems, or in
+-/etc/sysconfig/laptop-mode on other systems.
+-
+-Unfortunately, automatic enabling of laptop mode does not work for
+-laptops that don't have ACPI. On those laptops, you need to start laptop
+-mode manually. To start laptop mode, run "laptop_mode start", and to
+-stop it, run "laptop_mode stop". (Note: The laptop mode tools package now
+-has experimental support for APM, you might want to try that first.)
+-
+-
+-Caveats
+--------
+-
+-* The downside of laptop mode is that you have a chance of losing up to 10
+- minutes of work. If you cannot afford this, don't use it! The supplied ACPI
+- scripts automatically turn off laptop mode when the battery almost runs out,
+- so that you won't lose any data at the end of your battery life.
+-
+-* Most desktop hard drives have a very limited lifetime measured in spindown
+- cycles, typically about 50.000 times (it's usually listed on the spec sheet).
+- Check your drive's rating, and don't wear down your drive's lifetime if you
+- don't need to.
+-
+-* If you mount some of your ext3/reiserfs filesystems with the -n option, then
+- the control script will not be able to remount them correctly. You must set
+- DO_REMOUNTS=0 in the control script, otherwise it will remount them with the
+- wrong options -- or it will fail because it cannot write to /etc/mtab.
+-
+-* If you have your filesystems listed as type "auto" in fstab, like I did, then
+- the control script will not recognize them as filesystems that need remounting.
+- You must list the filesystems with their true type instead.
+-
+-* It has been reported that some versions of the mutt mail client use file access
+- times to determine whether a folder contains new mail. If you use mutt and
+- experience this, you must disable the noatime remounting by setting the option
+- DO_REMOUNT_NOATIME to 0 in the configuration file.
+-
+-
+-The Details
+------------
+-
+-Laptop mode is controlled by the knob /proc/sys/vm/laptop_mode. This knob is
+-present for all kernels that have the laptop mode patch, regardless of any
+-configuration options. When the knob is set, any physical disk I/O (that might
+-have caused the hard disk to spin up) causes Linux to flush all dirty blocks. The
+-result of this is that after a disk has spun down, it will not be spun up
+-anymore to write dirty blocks, because those blocks had already been written
+-immediately after the most recent read operation. The value of the laptop_mode
+-knob determines the time between the occurrence of disk I/O and when the flush
+-is triggered. A sensible value for the knob is 5 seconds. Setting the knob to
+-0 disables laptop mode.
+-
+-To increase the effectiveness of the laptop_mode strategy, the laptop_mode
+-control script increases dirty_expire_centisecs and dirty_writeback_centisecs in
+-/proc/sys/vm to about 10 minutes (by default), which means that pages that are
+-dirtied are not forced to be written to disk as often. The control script also
+-changes the dirty background ratio, so that background writeback of dirty pages
+-is not done anymore. Combined with a higher commit value (also 10 minutes) for
+-ext3 or ReiserFS filesystems (also done automatically by the control script),
+-this results in concentration of disk activity in a small time interval which
+-occurs only once every 10 minutes, or whenever the disk is forced to spin up by
+-a cache miss. The disk can then be spun down in the periods of inactivity.
+-
+-If you want to find out which process caused the disk to spin up, you can
+-gather information by setting the flag /proc/sys/vm/block_dump. When this flag
+-is set, Linux reports all disk read and write operations that take place, and
+-all block dirtyings done to files. This makes it possible to debug why a disk
+-needs to spin up, and to increase battery life even more. The output of
+-block_dump is written to the kernel output, and it can be retrieved using
+-"dmesg". When you use block_dump and your kernel logging level also includes
+-kernel debugging messages, you probably want to turn off klogd, otherwise
+-the output of block_dump will be logged, causing disk activity that is not
+-normally there.
+-
+-
+-Configuration
+--------------
+-
+-The laptop mode configuration file is located in /etc/default/laptop-mode on
+-Debian-based systems, or in /etc/sysconfig/laptop-mode on other systems. It
+-contains the following options:
+-
+-MAX_AGE:
+-
+-Maximum time, in seconds, of hard drive spindown time that you are
+-comfortable with. Worst case, it's possible that you could lose this
+-amount of work if your battery fails while you're in laptop mode.
+-
+-MINIMUM_BATTERY_MINUTES:
+-
+-Automatically disable laptop mode if the remaining number of minutes of
+-battery power is less than this value. Default is 10 minutes.
+-
+-AC_HD/BATT_HD:
+-
+-The idle timeout that should be set on your hard drive when laptop mode
+-is active (BATT_HD) and when it is not active (AC_HD). The defaults are
+-20 seconds (value 4) for BATT_HD and 2 hours (value 244) for AC_HD. The
+-possible values are those listed in the manual page for "hdparm" for the
+-"-S" option.
+-
+-HD:
+-
+-The devices for which the spindown timeout should be adjusted by laptop mode.
+-Default is /dev/hda. If you specify multiple devices, separate them by a space.
+-
+-READAHEAD:
+-
+-Disk readahead, in 512-byte sectors, while laptop mode is active. A large
+-readahead can prevent disk accesses for things like executable pages (which are
+-loaded on demand while the application executes) and sequentially accessed data
+-(MP3s).
+-
+-DO_REMOUNTS:
+-
+-The control script automatically remounts any mounted journaled filesystems
+-with appropriate commit interval options. When this option is set to 0, this
+-feature is disabled.
+-
+-DO_REMOUNT_NOATIME:
+-
+-When remounting, should the filesystems be remounted with the noatime option?
+-Normally, this is set to "1" (enabled), but there may be programs that require
+-access time recording.
+-
+-DIRTY_RATIO:
+-
+-The percentage of memory that is allowed to contain "dirty" or unsaved data
+-before a writeback is forced, while laptop mode is active. Corresponds to
+-the /proc/sys/vm/dirty_ratio sysctl.
+-
+-DIRTY_BACKGROUND_RATIO:
+-
+-The percentage of memory that is allowed to contain "dirty" or unsaved data
+-after a forced writeback is done due to an exceeding of DIRTY_RATIO. Set
+-this nice and low. This corresponds to the /proc/sys/vm/dirty_background_ratio
+-sysctl.
+-
+-Note that the behaviour of dirty_background_ratio is quite different
+-when laptop mode is active and when it isn't. When laptop mode is inactive,
+-dirty_background_ratio is the threshold percentage at which background writeouts
+-start taking place. When laptop mode is active, however, background writeouts
+-are disabled, and the dirty_background_ratio only determines how much writeback
+-is done when dirty_ratio is reached.
+-
+-DO_CPU:
+-
+-Enable CPU frequency scaling when in laptop mode. (Requires CPUFreq to be setup.
+-See Documentation/cpu-freq/user-guide.txt for more info. Disabled by default.)
+-
+-CPU_MAXFREQ:
+-
+-When on battery, what is the maximum CPU speed that the system should use? Legal
+-values are "slowest" for the slowest speed that your CPU is able to operate at,
+-or a value listed in /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies.
+-
+-
+-Tips & Tricks
+--------------
+-
+-* Bartek Kania reports getting up to 50 minutes of extra battery life (on top
+- of his regular 3 to 3.5 hours) using a spindown time of 5 seconds (BATT_HD=1).
+-
+-* You can spin down the disk while playing MP3, by setting disk readahead
+- to 8MB (READAHEAD=16384). Effectively, the disk will read a complete MP3 at
+- once, and will then spin down while the MP3 is playing. (Thanks to Bartek
+- Kania.)
+-
+-* Drew Scott Daniels observed: "I don't know why, but when I decrease the number
+- of colours that my display uses it consumes less battery power. I've seen
+- this on powerbooks too. I hope that this is a piece of information that
+- might be useful to the Laptop Mode patch or it's users."
+-
+-* In syslog.conf, you can prefix entries with a dash ``-'' to omit syncing the
+- file after every logging. When you're using laptop-mode and your disk doesn't
+- spin down, this is a likely culprit.
+-
+-* Richard Atterer observed that laptop mode does not work well with noflushd
+- (http://noflushd.sourceforge.net/), it seems that noflushd prevents laptop-mode
+- from doing its thing.
+-
+-* If you're worried about your data, you might want to consider using a USB
+- memory stick or something like that as a "working area". (Be aware though
+- that flash memory can only handle a limited number of writes, and overuse
+- may wear out your memory stick pretty quickly. Do _not_ use journalling
+- filesystems on flash memory sticks.)
+-
+-
+-Configuration file for control and ACPI battery scripts
+--------------------------------------------------------
+-
+-This allows the tunables to be changed for the scripts via an external
+-configuration file
+-
+-It should be installed as /etc/default/laptop-mode on Debian, and as
+-/etc/sysconfig/laptop-mode on Red Hat, SUSE, Mandrake, and other work-alikes.
+-
+---------------------CONFIG FILE BEGIN-------------------------------------------
+-# Maximum time, in seconds, of hard drive spindown time that you are
+-# comfortable with. Worst case, it's possible that you could lose this
+-# amount of work if your battery fails you while in laptop mode.
+-#MAX_AGE=600
+-
+-# Automatically disable laptop mode when the number of minutes of battery
+-# that you have left goes below this threshold.
+-MINIMUM_BATTERY_MINUTES=10
+-
+-# Read-ahead, in 512-byte sectors. You can spin down the disk while playing MP3/OGG
+-# by setting the disk readahead to 8MB (READAHEAD=16384). Effectively, the disk
+-# will read a complete MP3 at once, and will then spin down while the MP3/OGG is
+-# playing.
+-#READAHEAD=4096
+-
+-# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
+-#DO_REMOUNTS=1
+-
+-# And shall we add the "noatime" option to that as well? (1=yes)
+-#DO_REMOUNT_NOATIME=1
+-
+-# Dirty synchronous ratio. At this percentage of dirty pages the process
+-# which
+-# calls write() does its own writeback
+-#DIRTY_RATIO=40
+-
+-#
+-# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been
+-# exceeded, the kernel will wake pdflush which will then reduce the amount
+-# of dirty memory to dirty_background_ratio. Set this nice and low, so once
+-# some writeout has commenced, we do a lot of it.
+-#
+-#DIRTY_BACKGROUND_RATIO=5
+-
+-# kernel default dirty buffer age
+-#DEF_AGE=30
+-#DEF_UPDATE=5
+-#DEF_DIRTY_BACKGROUND_RATIO=10
+-#DEF_DIRTY_RATIO=40
+-#DEF_XFS_AGE_BUFFER=15
+-#DEF_XFS_SYNC_INTERVAL=30
+-#DEF_XFS_BUFD_INTERVAL=1
+-
+-# This must be adjusted manually to the value of HZ in the running kernel
+-# on 2.4, until the XFS people change their 2.4 external interfaces to work in
+-# centisecs. This can be automated, but it's a work in progress that still
+-# needs# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for
+-# external interfaces, and that is currently always set to 100. So you don't
+-# need to change this on 2.6.
+-#XFS_HZ=100
+-
+-# Should the maximum CPU frequency be adjusted down while on battery?
+-# Requires CPUFreq to be setup.
+-# See Documentation/cpu-freq/user-guide.txt for more info
+-#DO_CPU=0
+-
+-# When on battery what is the maximum CPU speed that the system should
+-# use? Legal values are "slowest" for the slowest speed that your
+-# CPU is able to operate at, or a value listed in:
+-# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
+-# Only applicable if DO_CPU=1.
+-#CPU_MAXFREQ=slowest
+-
+-# Idle timeout for your hard drive (man hdparm for valid values, -S option)
+-# Default is 2 hours on AC (AC_HD=244) and 20 seconds for battery (BATT_HD=4).
+-#AC_HD=244
+-#BATT_HD=4
+-
+-# The drives for which to adjust the idle timeout. Separate them by a space,
+-# e.g. HD="/dev/hda /dev/hdb".
+-#HD="/dev/hda"
+-
+-# Set the spindown timeout on a hard drive?
+-#DO_HD=1
+-
+---------------------CONFIG FILE END---------------------------------------------
+-
+-
+-Control script
+---------------
+-
+-Please note that this control script works for the Linux 2.4 and 2.6 series (thanks
+-to Kiko Piris).
+-
+---------------------CONTROL SCRIPT BEGIN----------------------------------------
+-#!/bin/bash
+-
+-# start or stop laptop_mode, best run by a power management daemon when
+-# ac gets connected/disconnected from a laptop
+-#
+-# install as /sbin/laptop_mode
+-#
+-# Contributors to this script: Kiko Piris
+-# Bart Samwel
+-# Micha Feigin
+-# Andrew Morton
+-# Herve Eychenne
+-# Dax Kelson
+-#
+-# Original Linux 2.4 version by: Jens Axboe
+-
+-#############################################################################
+-
+-# Source config
+-if [ -f /etc/default/laptop-mode ] ; then
+- # Debian
+- . /etc/default/laptop-mode
+-elif [ -f /etc/sysconfig/laptop-mode ] ; then
+- # Others
+- . /etc/sysconfig/laptop-mode
+-fi
+-
+-# Don't raise an error if the config file is incomplete
+-# set defaults instead:
+-
+-# Maximum time, in seconds, of hard drive spindown time that you are
+-# comfortable with. Worst case, it's possible that you could lose this
+-# amount of work if your battery fails you while in laptop mode.
+-MAX_AGE=${MAX_AGE:-'600'}
+-
+-# Read-ahead, in kilobytes
+-READAHEAD=${READAHEAD:-'4096'}
+-
+-# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
+-DO_REMOUNTS=${DO_REMOUNTS:-'1'}
+-
+-# And shall we add the "noatime" option to that as well? (1=yes)
+-DO_REMOUNT_NOATIME=${DO_REMOUNT_NOATIME:-'1'}
+-
+-# Shall we adjust the idle timeout on a hard drive?
+-DO_HD=${DO_HD:-'1'}
+-
+-# Adjust idle timeout on which hard drive?
+-HD="${HD:-'/dev/hda'}"
+-
+-# spindown time for HD (hdparm -S values)
+-AC_HD=${AC_HD:-'244'}
+-BATT_HD=${BATT_HD:-'4'}
+-
+-# Dirty synchronous ratio. At this percentage of dirty pages the process which
+-# calls write() does its own writeback
+-DIRTY_RATIO=${DIRTY_RATIO:-'40'}
+-
+-# cpu frequency scaling
+-# See Documentation/cpu-freq/user-guide.txt for more info
+-DO_CPU=${CPU_MANAGE:-'0'}
+-CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'}
+-
+-#
+-# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been
+-# exceeded, the kernel will wake pdflush which will then reduce the amount
+-# of dirty memory to dirty_background_ratio. Set this nice and low, so once
+-# some writeout has commenced, we do a lot of it.
+-#
+-DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'}
+-
+-# kernel default dirty buffer age
+-DEF_AGE=${DEF_AGE:-'30'}
+-DEF_UPDATE=${DEF_UPDATE:-'5'}
+-DEF_DIRTY_BACKGROUND_RATIO=${DEF_DIRTY_BACKGROUND_RATIO:-'10'}
+-DEF_DIRTY_RATIO=${DEF_DIRTY_RATIO:-'40'}
+-DEF_XFS_AGE_BUFFER=${DEF_XFS_AGE_BUFFER:-'15'}
+-DEF_XFS_SYNC_INTERVAL=${DEF_XFS_SYNC_INTERVAL:-'30'}
+-DEF_XFS_BUFD_INTERVAL=${DEF_XFS_BUFD_INTERVAL:-'1'}
+-
+-# This must be adjusted manually to the value of HZ in the running kernel
+-# on 2.4, until the XFS people change their 2.4 external interfaces to work in
+-# centisecs. This can be automated, but it's a work in progress that still needs
+-# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for external
+-# interfaces, and that is currently always set to 100. So you don't need to
+-# change this on 2.6.
+-XFS_HZ=${XFS_HZ:-'100'}
+-
+-#############################################################################
+-
+-KLEVEL="$(uname -r |
+- {
+- IFS='.' read a b c
+- echo $a.$b
+- }
+-)"
+-case "$KLEVEL" in
+- "2.4"|"2.6")
+- ;;
+- *)
+- echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2
+- exit 1
+- ;;
+-esac
+-
+-if [ ! -e /proc/sys/vm/laptop_mode ] ; then
+- echo "Kernel is not patched with laptop_mode patch." >&2
+- exit 1
+-fi
+-
+-if [ ! -w /proc/sys/vm/laptop_mode ] ; then
+- echo "You do not have enough privileges to enable laptop_mode." >&2
+- exit 1
+-fi
+-
+-# Remove an option (the first parameter) of the form option=<number> from
+-# a mount options string (the rest of the parameters).
+-parse_mount_opts () {
+- OPT="$1"
+- shift
+- echo ",$*," | sed \
+- -e 's/,'"$OPT"'=[0-9]*,/,/g' \
+- -e 's/,,*/,/g' \
+- -e 's/^,//' \
+- -e 's/,$//'
+-}
+-
+-# Remove an option (the first parameter) without any arguments from
+-# a mount option string (the rest of the parameters).
+-parse_nonumber_mount_opts () {
+- OPT="$1"
+- shift
+- echo ",$*," | sed \
+- -e 's/,'"$OPT"',/,/g' \
+- -e 's/,,*/,/g' \
+- -e 's/^,//' \
+- -e 's/,$//'
+-}
+-
+-# Find out the state of a yes/no option (e.g. "atime"/"noatime") in
+-# fstab for a given filesystem, and use this state to replace the
+-# value of the option in another mount options string. The device
+-# is the first argument, the option name the second, and the default
+-# value the third. The remainder is the mount options string.
+-#
+-# Example:
+-# parse_yesno_opts_wfstab /dev/hda1 atime atime defaults,noatime
+-#
+-# If fstab contains, say, "rw" for this filesystem, then the result
+-# will be "defaults,atime".
+-parse_yesno_opts_wfstab () {
+- L_DEV="$1"
+- OPT="$2"
+- DEF_OPT="$3"
+- shift 3
+- L_OPTS="$*"
+- PARSEDOPTS1="$(parse_nonumber_mount_opts $OPT $L_OPTS)"
+- PARSEDOPTS1="$(parse_nonumber_mount_opts no$OPT $PARSEDOPTS1)"
+- # Watch for a default atime in fstab
+- FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
+- if echo "$FSTAB_OPTS" | grep "$OPT" > /dev/null ; then
+- # option specified in fstab: extract the value and use it
+- if echo "$FSTAB_OPTS" | grep "no$OPT" > /dev/null ; then
+- echo "$PARSEDOPTS1,no$OPT"
+- else
+- # no$OPT not found -- so we must have $OPT.
+- echo "$PARSEDOPTS1,$OPT"
+- fi
+- else
+- # option not specified in fstab -- choose the default.
+- echo "$PARSEDOPTS1,$DEF_OPT"
+- fi
+-}
+-
+-# Find out the state of a numbered option (e.g. "commit=NNN") in
+-# fstab for a given filesystem, and use this state to replace the
+-# value of the option in another mount options string. The device
+-# is the first argument, and the option name the second. The
+-# remainder is the mount options string in which the replacement
+-# must be done.
+-#
+-# Example:
+-# parse_mount_opts_wfstab /dev/hda1 commit defaults,commit=7
+-#
+-# If fstab contains, say, "commit=3,rw" for this filesystem, then the
+-# result will be "rw,commit=3".
+-parse_mount_opts_wfstab () {
+- L_DEV="$1"
+- OPT="$2"
+- shift 2
+- L_OPTS="$*"
+- PARSEDOPTS1="$(parse_mount_opts $OPT $L_OPTS)"
+- # Watch for a default commit in fstab
+- FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
+- if echo "$FSTAB_OPTS" | grep "$OPT=" > /dev/null ; then
+- # option specified in fstab: extract the value, and use it
+- echo -n "$PARSEDOPTS1,$OPT="
+- echo ",$FSTAB_OPTS," | sed \
+- -e 's/.*,'"$OPT"'=//' \
+- -e 's/,.*//'
+- else
+- # option not specified in fstab: set it to 0
+- echo "$PARSEDOPTS1,$OPT=0"
+- fi
+-}
+-
+-deduce_fstype () {
+- MP="$1"
+- # My root filesystem unfortunately has
+- # type "unknown" in /etc/mtab. If we encounter
+- # "unknown", we try to get the type from fstab.
+- cat /etc/fstab |
+- grep -v '^#' |
+- while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do
+- if [ "$FSTAB_MP" = "$MP" ]; then
+- echo $FSTAB_FST
+- exit 0
+- fi
+- done
+-}
+-
+-if [ $DO_REMOUNT_NOATIME -eq 1 ] ; then
+- NOATIME_OPT=",noatime"
+-fi
+-
+-case "$1" in
+- start)
+- AGE=$((100*$MAX_AGE))
+- XFS_AGE=$(($XFS_HZ*$MAX_AGE))
+- echo -n "Starting laptop_mode"
+-
+- if [ -d /proc/sys/vm/pagebuf ] ; then
+- # (For 2.4 and early 2.6.)
+- # This only needs to be set, not reset -- it is only used when
+- # laptop mode is enabled.
+- echo $XFS_AGE > /proc/sys/vm/pagebuf/lm_flush_age
+- echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
+- elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
+- # (A couple of early 2.6 laptop mode patches had these.)
+- # The same goes for these.
+- echo $XFS_AGE > /proc/sys/fs/xfs/lm_age_buffer
+- echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
+- elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
+- # (2.6.6)
+- # But not for these -- they are also used in normal
+- # operation.
+- echo $XFS_AGE > /proc/sys/fs/xfs/age_buffer
+- echo $XFS_AGE > /proc/sys/fs/xfs/sync_interval
+- elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
+- # (2.6.7 upwards)
+- # And not for these either. These are in centisecs,
+- # not USER_HZ, so we have to use $AGE, not $XFS_AGE.
+- echo $AGE > /proc/sys/fs/xfs/age_buffer_centisecs
+- echo $AGE > /proc/sys/fs/xfs/xfssyncd_centisecs
+- echo 3000 > /proc/sys/fs/xfs/xfsbufd_centisecs
+- fi
+-
+- case "$KLEVEL" in
+- "2.4")
+- echo 1 > /proc/sys/vm/laptop_mode
+- echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush
+- ;;
+- "2.6")
+- echo 5 > /proc/sys/vm/laptop_mode
+- echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs
+- echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs
+- echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_ratio
+- echo "$DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio
+- ;;
+- esac
+- if [ $DO_REMOUNTS -eq 1 ]; then
+- cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
+- PARSEDOPTS="$(parse_mount_opts "$OPTS")"
+- if [ "$FST" = 'unknown' ]; then
+- FST=$(deduce_fstype $MP)
+- fi
+- case "$FST" in
+- "ext3"|"reiserfs")
+- PARSEDOPTS="$(parse_mount_opts commit "$OPTS")"
+- mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT
+- ;;
+- "xfs")
+- mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT
+- ;;
+- esac
+- if [ -b $DEV ] ; then
+- blockdev --setra $(($READAHEAD * 2)) $DEV
+- fi
+- done
+- fi
+- if [ $DO_HD -eq 1 ] ; then
+- for THISHD in $HD ; do
+- /sbin/hdparm -S $BATT_HD $THISHD > /dev/null 2>&1
+- /sbin/hdparm -B 1 $THISHD > /dev/null 2>&1
+- done
+- fi
+- if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
+- if [ $CPU_MAXFREQ = 'slowest' ]; then
+- CPU_MAXFREQ=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
+- fi
+- echo $CPU_MAXFREQ > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
+- fi
+- echo "."
+- ;;
+- stop)
+- U_AGE=$((100*$DEF_UPDATE))
+- B_AGE=$((100*$DEF_AGE))
+- echo -n "Stopping laptop_mode"
+- echo 0 > /proc/sys/vm/laptop_mode
+- if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
+- # These need to be restored, if there are no lm_*.
+- echo $(($XFS_HZ*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer
+- echo $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/sync_interval
+- elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
+- # These need to be restored as well.
+- echo $((100*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer_centisecs
+- echo $((100*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/xfssyncd_centisecs
+- echo $((100*$DEF_XFS_BUFD_INTERVAL)) > /proc/sys/fs/xfs/xfsbufd_centisecs
+- fi
+- case "$KLEVEL" in
+- "2.4")
+- echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush
+- ;;
+- "2.6")
+- echo "$U_AGE" > /proc/sys/vm/dirty_writeback_centisecs
+- echo "$B_AGE" > /proc/sys/vm/dirty_expire_centisecs
+- echo "$DEF_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio
+- echo "$DEF_DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio
+- ;;
+- esac
+- if [ $DO_REMOUNTS -eq 1 ] ; then
+- cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
+- # Reset commit and atime options to defaults.
+- if [ "$FST" = 'unknown' ]; then
+- FST=$(deduce_fstype $MP)
+- fi
+- case "$FST" in
+- "ext3"|"reiserfs")
+- PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)"
+- PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)"
+- mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
+- ;;
+- "xfs")
+- PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $OPTS)"
+- mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
+- ;;
+- esac
+- if [ -b $DEV ] ; then
+- blockdev --setra 256 $DEV
+- fi
+- done
+- fi
+- if [ $DO_HD -eq 1 ] ; then
+- for THISHD in $HD ; do
+- /sbin/hdparm -S $AC_HD $THISHD > /dev/null 2>&1
+- /sbin/hdparm -B 255 $THISHD > /dev/null 2>&1
+- done
+- fi
+- if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
+- echo `cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
+- fi
+- echo "."
+- ;;
+- *)
+- echo "Usage: $0 {start|stop}" 2>&1
+- exit 1
+- ;;
+-
+-esac
+-
+-exit 0
+---------------------CONTROL SCRIPT END------------------------------------------
+-
+-
+-ACPI integration
+-----------------
+-
+-Dax Kelson submitted this so that the ACPI acpid daemon will
+-kick off the laptop_mode script and run hdparm. The part that
+-automatically disables laptop mode when the battery is low was
+-written by Jan Topinski.
+-
+------------------/etc/acpi/events/ac_adapter BEGIN------------------------------
+-event=ac_adapter
+-action=/etc/acpi/actions/ac.sh %e
+-----------------/etc/acpi/events/ac_adapter END---------------------------------
+-
+-
+------------------/etc/acpi/events/battery BEGIN---------------------------------
+-event=battery.*
+-action=/etc/acpi/actions/battery.sh %e
+-----------------/etc/acpi/events/battery END------------------------------------
+-
+-
+-----------------/etc/acpi/actions/ac.sh BEGIN-----------------------------------
+-#!/bin/bash
+-
+-# ac on/offline event handler
+-
+-status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/$2/state`
+-
+-case $status in
+- "on-line")
+- /sbin/laptop_mode stop
+- exit 0
+- ;;
+- "off-line")
+- /sbin/laptop_mode start
+- exit 0
+- ;;
+-esac
+----------------------------/etc/acpi/actions/ac.sh END--------------------------
+-
+-
+----------------------------/etc/acpi/actions/battery.sh BEGIN-------------------
+-#! /bin/bash
+-
+-# Automatically disable laptop mode when the battery almost runs out.
+-
+-BATT_INFO=/proc/acpi/battery/$2/state
+-
+-if [[ -f /proc/sys/vm/laptop_mode ]]
+-then
+- LM=`cat /proc/sys/vm/laptop_mode`
+- if [[ $LM -gt 0 ]]
+- then
+- if [[ -f $BATT_INFO ]]
+- then
+- # Source the config file only now that we know we need
+- if [ -f /etc/default/laptop-mode ] ; then
+- # Debian
+- . /etc/default/laptop-mode
+- elif [ -f /etc/sysconfig/laptop-mode ] ; then
+- # Others
+- . /etc/sysconfig/laptop-mode
+- fi
+- MINIMUM_BATTERY_MINUTES=${MINIMUM_BATTERY_MINUTES:-'10'}
+-
+- ACTION="`cat $BATT_INFO | grep charging | cut -c 26-`"
+- if [[ ACTION -eq "discharging" ]]
+- then
+- PRESENT_RATE=`cat $BATT_INFO | grep "present rate:" | sed "s/.* \([0-9][0-9]* \).*/\1/" `
+- REMAINING=`cat $BATT_INFO | grep "remaining capacity:" | sed "s/.* \([0-9][0-9]* \).*/\1/" `
+- fi
+- if (($REMAINING * 60 / $PRESENT_RATE < $MINIMUM_BATTERY_MINUTES))
+- then
+- /sbin/laptop_mode stop
+- fi
+- else
+- logger -p daemon.warning "You are using laptop mode and your battery interface $BATT_INFO is missing. This may lead to loss of data when the battery runs out. Check kernel ACPI support and /proc/acpi/battery folder, and edit /etc/acpi/battery.sh to set BATT_INFO to the correct path."
+- fi
+- fi
+-fi
+----------------------------/etc/acpi/actions/battery.sh END--------------------
+-
+-
+-Monitoring tool
+----------------
+-
+-Bartek Kania submitted this, it can be used to measure how much time your disk
+-spends spun up/down.
+-
+----------------------------dslm.c BEGIN-----------------------------------------
+-/*
+- * Simple Disk Sleep Monitor
+- * by Bartek Kania
+- * Licenced under the GPL
+- */
+-#include <unistd.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <fcntl.h>
+-#include <errno.h>
+-#include <time.h>
+-#include <string.h>
+-#include <signal.h>
+-#include <sys/ioctl.h>
+-#include <linux/hdreg.h>
+-
+-#ifdef DEBUG
+-#define D(x) x
+-#else
+-#define D(x)
+-#endif
+-
+-int endit = 0;
+-
+-/* Check if the disk is in powersave-mode
+- * Most of the code is stolen from hdparm.
+- * 1 = active, 0 = standby/sleep, -1 = unknown */
+-int check_powermode(int fd)
+-{
+- unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
+- int state;
+-
+- if (ioctl(fd, HDIO_DRIVE_CMD, &args)
+- && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
+- && ioctl(fd, HDIO_DRIVE_CMD, &args)) {
+- if (errno != EIO || args[0] != 0 || args[1] != 0) {
+- state = -1; /* "unknown"; */
+- } else
+- state = 0; /* "sleeping"; */
+- } else {
+- state = (args[2] == 255) ? 1 : 0;
+- }
+- D(printf(" drive state is: %d\n", state));
+-
+- return state;
+-}
+-
+-char *state_name(int i)
+-{
+- if (i == -1) return "unknown";
+- if (i == 0) return "sleeping";
+- if (i == 1) return "active";
+-
+- return "internal error";
+-}
+-
+-char *myctime(time_t time)
+-{
+- char *ts = ctime(&time);
+- ts[strlen(ts) - 1] = 0;
+-
+- return ts;
+-}
+-
+-void measure(int fd)
+-{
+- time_t start_time;
+- int last_state;
+- time_t last_time;
+- int curr_state;
+- time_t curr_time = 0;
+- time_t time_diff;
+- time_t active_time = 0;
+- time_t sleep_time = 0;
+- time_t unknown_time = 0;
+- time_t total_time = 0;
+- int changes = 0;
+- float tmp;
+-
+- printf("Starting measurements\n");
+-
+- last_state = check_powermode(fd);
+- start_time = last_time = time(0);
+- printf(" System is in state %s\n\n", state_name(last_state));
+-
+- while(!endit) {
+- sleep(1);
+- curr_state = check_powermode(fd);
+-
+- if (curr_state != last_state || endit) {
+- changes++;
+- curr_time = time(0);
+- time_diff = curr_time - last_time;
+-
+- if (last_state == 1) active_time += time_diff;
+- else if (last_state == 0) sleep_time += time_diff;
+- else unknown_time += time_diff;
+-
+- last_state = curr_state;
+- last_time = curr_time;
+-
+- printf("%s: State-change to %s\n", myctime(curr_time),
+- state_name(curr_state));
+- }
+- }
+- changes--; /* Compensate for SIGINT */
+-
+- total_time = time(0) - start_time;
+- printf("\nTotal running time: %lus\n", curr_time - start_time);
+- printf(" State changed %d times\n", changes);
+-
+- tmp = (float)sleep_time / (float)total_time * 100;
+- printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp);
+- tmp = (float)active_time / (float)total_time * 100;
+- printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp);
+- tmp = (float)unknown_time / (float)total_time * 100;
+- printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
+-}
+-
+-void ender(int s)
+-{
+- endit = 1;
+-}
+-
+-void usage()
+-{
+- puts("usage: dslm [-w <time>] <disk>");
+- exit(0);
+-}
+-
+-int main(int argc, char **argv)
+-{
+- int fd;
+- char *disk = 0;
+- int settle_time = 60;
+-
+- /* Parse the simple command-line */
+- if (argc == 2)
+- disk = argv[1];
+- else if (argc == 4) {
+- settle_time = atoi(argv[2]);
+- disk = argv[3];
+- } else
+- usage();
+-
+- if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
+- printf("Can't open %s, because: %s\n", disk, strerror(errno));
+- exit(-1);
+- }
+-
+- if (settle_time) {
+- printf("Waiting %d seconds for the system to settle down to "
+- "'normal'\n", settle_time);
+- sleep(settle_time);
+- } else
+- puts("Not waiting for system to settle down");
+-
+- signal(SIGINT, ender);
+-
+- measure(fd);
+-
+- close(fd);
+-
+- return 0;
+-}
+----------------------------dslm.c END-------------------------------------------
+diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX
+index 729c2c0..ee5692b 100644
+--- a/Documentation/laptops/00-INDEX
++++ b/Documentation/laptops/00-INDEX
+@@ -2,6 +2,8 @@
+ - This file
+ acer-wmi.txt
+ - information on the Acer Laptop WMI Extras driver.
++laptop-mode.txt
++ - how to conserve battery power using laptop-mode.
+ sony-laptop.txt
+ - Sony Notebook Control Driver (SNC) Readme.
+ sonypi.txt
+diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
+index b066963..23df051 100644
+--- a/Documentation/laptops/acer-wmi.txt
++++ b/Documentation/laptops/acer-wmi.txt
+@@ -48,7 +48,7 @@ DSDT.
+
+ To send me the DSDT, as root/sudo:
+
+-cat /sys/firmware/acpi/DSDT > dsdt
++cat /sys/firmware/acpi/tables/DSDT > dsdt
+
+ And send me the resulting 'dsdt' file.
+
+@@ -169,7 +169,7 @@ can be added to acer-wmi.
+
+ The LED is exposed through the LED subsystem, and can be found in:
+
+-/sys/devices/platform/acer-wmi/leds/acer-mail:green/
++/sys/devices/platform/acer-wmi/leds/acer-wmi::mail/
+
+ The mail LED is autodetected, so if you don't have one, the LED device won't
+ be registered.
+diff --git a/Documentation/laptops/laptop-mode.txt b/Documentation/laptops/laptop-mode.txt
+new file mode 100644
+index 0000000..eeedee1
+--- /dev/null
++++ b/Documentation/laptops/laptop-mode.txt
+@@ -0,0 +1,950 @@
++How to conserve battery power using laptop-mode
++-----------------------------------------------
++
++Document Author: Bart Samwel (bart at samwel.tk)
++Date created: January 2, 2004
++Last modified: December 06, 2004
++
++Introduction
++------------
++
++Laptop mode is used to minimize the time that the hard disk needs to be spun up,
++to conserve battery power on laptops. It has been reported to cause significant
++power savings.
++
++Contents
++--------
++
++* Introduction
++* Installation
++* Caveats
++* The Details
++* Tips & Tricks
++* Control script
++* ACPI integration
++* Monitoring tool
++
++
++Installation
++------------
++
++To use laptop mode, you don't need to set any kernel configuration options
++or anything. Simply install all the files included in this document, and
++laptop mode will automatically be started when you're on battery. For
++your convenience, a tarball containing an installer can be downloaded at:
++
++http://www.samwel.tk/laptop_mode/laptop_mode/
++
++To configure laptop mode, you need to edit the configuration file, which is
++located in /etc/default/laptop-mode on Debian-based systems, or in
++/etc/sysconfig/laptop-mode on other systems.
++
++Unfortunately, automatic enabling of laptop mode does not work for
++laptops that don't have ACPI. On those laptops, you need to start laptop
++mode manually. To start laptop mode, run "laptop_mode start", and to
++stop it, run "laptop_mode stop". (Note: The laptop mode tools package now
++has experimental support for APM, you might want to try that first.)
++
++
++Caveats
++-------
++
++* The downside of laptop mode is that you have a chance of losing up to 10
++ minutes of work. If you cannot afford this, don't use it! The supplied ACPI
++ scripts automatically turn off laptop mode when the battery almost runs out,
++ so that you won't lose any data at the end of your battery life.
++
++* Most desktop hard drives have a very limited lifetime measured in spindown
++ cycles, typically about 50.000 times (it's usually listed on the spec sheet).
++ Check your drive's rating, and don't wear down your drive's lifetime if you
++ don't need to.
++
++* If you mount some of your ext3/reiserfs filesystems with the -n option, then
++ the control script will not be able to remount them correctly. You must set
++ DO_REMOUNTS=0 in the control script, otherwise it will remount them with the
++ wrong options -- or it will fail because it cannot write to /etc/mtab.
++
++* If you have your filesystems listed as type "auto" in fstab, like I did, then
++ the control script will not recognize them as filesystems that need remounting.
++ You must list the filesystems with their true type instead.
++
++* It has been reported that some versions of the mutt mail client use file access
++ times to determine whether a folder contains new mail. If you use mutt and
++ experience this, you must disable the noatime remounting by setting the option
++ DO_REMOUNT_NOATIME to 0 in the configuration file.
++
++
++The Details
++-----------
++
++Laptop mode is controlled by the knob /proc/sys/vm/laptop_mode. This knob is
++present for all kernels that have the laptop mode patch, regardless of any
++configuration options. When the knob is set, any physical disk I/O (that might
++have caused the hard disk to spin up) causes Linux to flush all dirty blocks. The
++result of this is that after a disk has spun down, it will not be spun up
++anymore to write dirty blocks, because those blocks had already been written
++immediately after the most recent read operation. The value of the laptop_mode
++knob determines the time between the occurrence of disk I/O and when the flush
++is triggered. A sensible value for the knob is 5 seconds. Setting the knob to
++0 disables laptop mode.
++
++To increase the effectiveness of the laptop_mode strategy, the laptop_mode
++control script increases dirty_expire_centisecs and dirty_writeback_centisecs in
++/proc/sys/vm to about 10 minutes (by default), which means that pages that are
++dirtied are not forced to be written to disk as often. The control script also
++changes the dirty background ratio, so that background writeback of dirty pages
++is not done anymore. Combined with a higher commit value (also 10 minutes) for
++ext3 or ReiserFS filesystems (also done automatically by the control script),
++this results in concentration of disk activity in a small time interval which
++occurs only once every 10 minutes, or whenever the disk is forced to spin up by
++a cache miss. The disk can then be spun down in the periods of inactivity.
++
++If you want to find out which process caused the disk to spin up, you can
++gather information by setting the flag /proc/sys/vm/block_dump. When this flag
++is set, Linux reports all disk read and write operations that take place, and
++all block dirtyings done to files. This makes it possible to debug why a disk
++needs to spin up, and to increase battery life even more. The output of
++block_dump is written to the kernel output, and it can be retrieved using
++"dmesg". When you use block_dump and your kernel logging level also includes
++kernel debugging messages, you probably want to turn off klogd, otherwise
++the output of block_dump will be logged, causing disk activity that is not
++normally there.
++
++
++Configuration
++-------------
++
++The laptop mode configuration file is located in /etc/default/laptop-mode on
++Debian-based systems, or in /etc/sysconfig/laptop-mode on other systems. It
++contains the following options:
++
++MAX_AGE:
++
++Maximum time, in seconds, of hard drive spindown time that you are
++comfortable with. Worst case, it's possible that you could lose this
++amount of work if your battery fails while you're in laptop mode.
++
++MINIMUM_BATTERY_MINUTES:
++
++Automatically disable laptop mode if the remaining number of minutes of
++battery power is less than this value. Default is 10 minutes.
++
++AC_HD/BATT_HD:
++
++The idle timeout that should be set on your hard drive when laptop mode
++is active (BATT_HD) and when it is not active (AC_HD). The defaults are
++20 seconds (value 4) for BATT_HD and 2 hours (value 244) for AC_HD. The
++possible values are those listed in the manual page for "hdparm" for the
++"-S" option.
++
++HD:
++
++The devices for which the spindown timeout should be adjusted by laptop mode.
++Default is /dev/hda. If you specify multiple devices, separate them by a space.
++
++READAHEAD:
++
++Disk readahead, in 512-byte sectors, while laptop mode is active. A large
++readahead can prevent disk accesses for things like executable pages (which are
++loaded on demand while the application executes) and sequentially accessed data
++(MP3s).
++
++DO_REMOUNTS:
++
++The control script automatically remounts any mounted journaled filesystems
++with appropriate commit interval options. When this option is set to 0, this
++feature is disabled.
++
++DO_REMOUNT_NOATIME:
++
++When remounting, should the filesystems be remounted with the noatime option?
++Normally, this is set to "1" (enabled), but there may be programs that require
++access time recording.
++
++DIRTY_RATIO:
++
++The percentage of memory that is allowed to contain "dirty" or unsaved data
++before a writeback is forced, while laptop mode is active. Corresponds to
++the /proc/sys/vm/dirty_ratio sysctl.
++
++DIRTY_BACKGROUND_RATIO:
++
++The percentage of memory that is allowed to contain "dirty" or unsaved data
++after a forced writeback is done due to an exceeding of DIRTY_RATIO. Set
++this nice and low. This corresponds to the /proc/sys/vm/dirty_background_ratio
++sysctl.
++
++Note that the behaviour of dirty_background_ratio is quite different
++when laptop mode is active and when it isn't. When laptop mode is inactive,
++dirty_background_ratio is the threshold percentage at which background writeouts
++start taking place. When laptop mode is active, however, background writeouts
++are disabled, and the dirty_background_ratio only determines how much writeback
++is done when dirty_ratio is reached.
++
++DO_CPU:
++
++Enable CPU frequency scaling when in laptop mode. (Requires CPUFreq to be setup.
++See Documentation/cpu-freq/user-guide.txt for more info. Disabled by default.)
++
++CPU_MAXFREQ:
++
++When on battery, what is the maximum CPU speed that the system should use? Legal
++values are "slowest" for the slowest speed that your CPU is able to operate at,
++or a value listed in /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies.
++
++
++Tips & Tricks
++-------------
++
++* Bartek Kania reports getting up to 50 minutes of extra battery life (on top
++ of his regular 3 to 3.5 hours) using a spindown time of 5 seconds (BATT_HD=1).
++
++* You can spin down the disk while playing MP3, by setting disk readahead
++ to 8MB (READAHEAD=16384). Effectively, the disk will read a complete MP3 at
++ once, and will then spin down while the MP3 is playing. (Thanks to Bartek
++ Kania.)
++
++* Drew Scott Daniels observed: "I don't know why, but when I decrease the number
++ of colours that my display uses it consumes less battery power. I've seen
++ this on powerbooks too. I hope that this is a piece of information that
++ might be useful to the Laptop Mode patch or it's users."
++
++* In syslog.conf, you can prefix entries with a dash ``-'' to omit syncing the
++ file after every logging. When you're using laptop-mode and your disk doesn't
++ spin down, this is a likely culprit.
++
++* Richard Atterer observed that laptop mode does not work well with noflushd
++ (http://noflushd.sourceforge.net/), it seems that noflushd prevents laptop-mode
++ from doing its thing.
++
++* If you're worried about your data, you might want to consider using a USB
++ memory stick or something like that as a "working area". (Be aware though
++ that flash memory can only handle a limited number of writes, and overuse
++ may wear out your memory stick pretty quickly. Do _not_ use journalling
++ filesystems on flash memory sticks.)
++
++
++Configuration file for control and ACPI battery scripts
++-------------------------------------------------------
++
++This allows the tunables to be changed for the scripts via an external
++configuration file
++
++It should be installed as /etc/default/laptop-mode on Debian, and as
++/etc/sysconfig/laptop-mode on Red Hat, SUSE, Mandrake, and other work-alikes.
++
++--------------------CONFIG FILE BEGIN-------------------------------------------
++# Maximum time, in seconds, of hard drive spindown time that you are
++# comfortable with. Worst case, it's possible that you could lose this
++# amount of work if your battery fails you while in laptop mode.
++#MAX_AGE=600
++
++# Automatically disable laptop mode when the number of minutes of battery
++# that you have left goes below this threshold.
++MINIMUM_BATTERY_MINUTES=10
++
++# Read-ahead, in 512-byte sectors. You can spin down the disk while playing MP3/OGG
++# by setting the disk readahead to 8MB (READAHEAD=16384). Effectively, the disk
++# will read a complete MP3 at once, and will then spin down while the MP3/OGG is
++# playing.
++#READAHEAD=4096
++
++# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
++#DO_REMOUNTS=1
++
++# And shall we add the "noatime" option to that as well? (1=yes)
++#DO_REMOUNT_NOATIME=1
++
++# Dirty synchronous ratio. At this percentage of dirty pages the process
++# which
++# calls write() does its own writeback
++#DIRTY_RATIO=40
++
++#
++# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been
++# exceeded, the kernel will wake pdflush which will then reduce the amount
++# of dirty memory to dirty_background_ratio. Set this nice and low, so once
++# some writeout has commenced, we do a lot of it.
++#
++#DIRTY_BACKGROUND_RATIO=5
++
++# kernel default dirty buffer age
++#DEF_AGE=30
++#DEF_UPDATE=5
++#DEF_DIRTY_BACKGROUND_RATIO=10
++#DEF_DIRTY_RATIO=40
++#DEF_XFS_AGE_BUFFER=15
++#DEF_XFS_SYNC_INTERVAL=30
++#DEF_XFS_BUFD_INTERVAL=1
++
++# This must be adjusted manually to the value of HZ in the running kernel
++# on 2.4, until the XFS people change their 2.4 external interfaces to work in
++# centisecs. This can be automated, but it's a work in progress that still
++# needs# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for
++# external interfaces, and that is currently always set to 100. So you don't
++# need to change this on 2.6.
++#XFS_HZ=100
++
++# Should the maximum CPU frequency be adjusted down while on battery?
++# Requires CPUFreq to be setup.
++# See Documentation/cpu-freq/user-guide.txt for more info
++#DO_CPU=0
++
++# When on battery what is the maximum CPU speed that the system should
++# use? Legal values are "slowest" for the slowest speed that your
++# CPU is able to operate at, or a value listed in:
++# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
++# Only applicable if DO_CPU=1.
++#CPU_MAXFREQ=slowest
++
++# Idle timeout for your hard drive (man hdparm for valid values, -S option)
++# Default is 2 hours on AC (AC_HD=244) and 20 seconds for battery (BATT_HD=4).
++#AC_HD=244
++#BATT_HD=4
++
++# The drives for which to adjust the idle timeout. Separate them by a space,
++# e.g. HD="/dev/hda /dev/hdb".
++#HD="/dev/hda"
++
++# Set the spindown timeout on a hard drive?
++#DO_HD=1
++
++--------------------CONFIG FILE END---------------------------------------------
++
++
++Control script
++--------------
++
++Please note that this control script works for the Linux 2.4 and 2.6 series (thanks
++to Kiko Piris).
++
++--------------------CONTROL SCRIPT BEGIN----------------------------------------
++#!/bin/bash
++
++# start or stop laptop_mode, best run by a power management daemon when
++# ac gets connected/disconnected from a laptop
++#
++# install as /sbin/laptop_mode
++#
++# Contributors to this script: Kiko Piris
++# Bart Samwel
++# Micha Feigin
++# Andrew Morton
++# Herve Eychenne
++# Dax Kelson
++#
++# Original Linux 2.4 version by: Jens Axboe
++
++#############################################################################
++
++# Source config
++if [ -f /etc/default/laptop-mode ] ; then
++ # Debian
++ . /etc/default/laptop-mode
++elif [ -f /etc/sysconfig/laptop-mode ] ; then
++ # Others
++ . /etc/sysconfig/laptop-mode
++fi
++
++# Don't raise an error if the config file is incomplete
++# set defaults instead:
++
++# Maximum time, in seconds, of hard drive spindown time that you are
++# comfortable with. Worst case, it's possible that you could lose this
++# amount of work if your battery fails you while in laptop mode.
++MAX_AGE=${MAX_AGE:-'600'}
++
++# Read-ahead, in kilobytes
++READAHEAD=${READAHEAD:-'4096'}
++
++# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
++DO_REMOUNTS=${DO_REMOUNTS:-'1'}
++
++# And shall we add the "noatime" option to that as well? (1=yes)
++DO_REMOUNT_NOATIME=${DO_REMOUNT_NOATIME:-'1'}
++
++# Shall we adjust the idle timeout on a hard drive?
++DO_HD=${DO_HD:-'1'}
++
++# Adjust idle timeout on which hard drive?
++HD="${HD:-'/dev/hda'}"
++
++# spindown time for HD (hdparm -S values)
++AC_HD=${AC_HD:-'244'}
++BATT_HD=${BATT_HD:-'4'}
++
++# Dirty synchronous ratio. At this percentage of dirty pages the process which
++# calls write() does its own writeback
++DIRTY_RATIO=${DIRTY_RATIO:-'40'}
++
++# cpu frequency scaling
++# See Documentation/cpu-freq/user-guide.txt for more info
++DO_CPU=${CPU_MANAGE:-'0'}
++CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'}
++
++#
++# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been
++# exceeded, the kernel will wake pdflush which will then reduce the amount
++# of dirty memory to dirty_background_ratio. Set this nice and low, so once
++# some writeout has commenced, we do a lot of it.
++#
++DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'}
++
++# kernel default dirty buffer age
++DEF_AGE=${DEF_AGE:-'30'}
++DEF_UPDATE=${DEF_UPDATE:-'5'}
++DEF_DIRTY_BACKGROUND_RATIO=${DEF_DIRTY_BACKGROUND_RATIO:-'10'}
++DEF_DIRTY_RATIO=${DEF_DIRTY_RATIO:-'40'}
++DEF_XFS_AGE_BUFFER=${DEF_XFS_AGE_BUFFER:-'15'}
++DEF_XFS_SYNC_INTERVAL=${DEF_XFS_SYNC_INTERVAL:-'30'}
++DEF_XFS_BUFD_INTERVAL=${DEF_XFS_BUFD_INTERVAL:-'1'}
++
++# This must be adjusted manually to the value of HZ in the running kernel
++# on 2.4, until the XFS people change their 2.4 external interfaces to work in
++# centisecs. This can be automated, but it's a work in progress that still needs
++# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for external
++# interfaces, and that is currently always set to 100. So you don't need to
++# change this on 2.6.
++XFS_HZ=${XFS_HZ:-'100'}
++
++#############################################################################
++
++KLEVEL="$(uname -r |
++ {
++ IFS='.' read a b c
++ echo $a.$b
++ }
++)"
++case "$KLEVEL" in
++ "2.4"|"2.6")
++ ;;
++ *)
++ echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2
++ exit 1
++ ;;
++esac
++
++if [ ! -e /proc/sys/vm/laptop_mode ] ; then
++ echo "Kernel is not patched with laptop_mode patch." >&2
++ exit 1
++fi
++
++if [ ! -w /proc/sys/vm/laptop_mode ] ; then
++ echo "You do not have enough privileges to enable laptop_mode." >&2
++ exit 1
++fi
++
++# Remove an option (the first parameter) of the form option=<number> from
++# a mount options string (the rest of the parameters).
++parse_mount_opts () {
++ OPT="$1"
++ shift
++ echo ",$*," | sed \
++ -e 's/,'"$OPT"'=[0-9]*,/,/g' \
++ -e 's/,,*/,/g' \
++ -e 's/^,//' \
++ -e 's/,$//'
++}
++
++# Remove an option (the first parameter) without any arguments from
++# a mount option string (the rest of the parameters).
++parse_nonumber_mount_opts () {
++ OPT="$1"
++ shift
++ echo ",$*," | sed \
++ -e 's/,'"$OPT"',/,/g' \
++ -e 's/,,*/,/g' \
++ -e 's/^,//' \
++ -e 's/,$//'
++}
++
++# Find out the state of a yes/no option (e.g. "atime"/"noatime") in
++# fstab for a given filesystem, and use this state to replace the
++# value of the option in another mount options string. The device
++# is the first argument, the option name the second, and the default
++# value the third. The remainder is the mount options string.
++#
++# Example:
++# parse_yesno_opts_wfstab /dev/hda1 atime atime defaults,noatime
++#
++# If fstab contains, say, "rw" for this filesystem, then the result
++# will be "defaults,atime".
++parse_yesno_opts_wfstab () {
++ L_DEV="$1"
++ OPT="$2"
++ DEF_OPT="$3"
++ shift 3
++ L_OPTS="$*"
++ PARSEDOPTS1="$(parse_nonumber_mount_opts $OPT $L_OPTS)"
++ PARSEDOPTS1="$(parse_nonumber_mount_opts no$OPT $PARSEDOPTS1)"
++ # Watch for a default atime in fstab
++ FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
++ if echo "$FSTAB_OPTS" | grep "$OPT" > /dev/null ; then
++ # option specified in fstab: extract the value and use it
++ if echo "$FSTAB_OPTS" | grep "no$OPT" > /dev/null ; then
++ echo "$PARSEDOPTS1,no$OPT"
++ else
++ # no$OPT not found -- so we must have $OPT.
++ echo "$PARSEDOPTS1,$OPT"
++ fi
++ else
++ # option not specified in fstab -- choose the default.
++ echo "$PARSEDOPTS1,$DEF_OPT"
++ fi
++}
++
++# Find out the state of a numbered option (e.g. "commit=NNN") in
++# fstab for a given filesystem, and use this state to replace the
++# value of the option in another mount options string. The device
++# is the first argument, and the option name the second. The
++# remainder is the mount options string in which the replacement
++# must be done.
++#
++# Example:
++# parse_mount_opts_wfstab /dev/hda1 commit defaults,commit=7
++#
++# If fstab contains, say, "commit=3,rw" for this filesystem, then the
++# result will be "rw,commit=3".
++parse_mount_opts_wfstab () {
++ L_DEV="$1"
++ OPT="$2"
++ shift 2
++ L_OPTS="$*"
++ PARSEDOPTS1="$(parse_mount_opts $OPT $L_OPTS)"
++ # Watch for a default commit in fstab
++ FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
++ if echo "$FSTAB_OPTS" | grep "$OPT=" > /dev/null ; then
++ # option specified in fstab: extract the value, and use it
++ echo -n "$PARSEDOPTS1,$OPT="
++ echo ",$FSTAB_OPTS," | sed \
++ -e 's/.*,'"$OPT"'=//' \
++ -e 's/,.*//'
++ else
++ # option not specified in fstab: set it to 0
++ echo "$PARSEDOPTS1,$OPT=0"
++ fi
++}
++
++deduce_fstype () {
++ MP="$1"
++ # My root filesystem unfortunately has
++ # type "unknown" in /etc/mtab. If we encounter
++ # "unknown", we try to get the type from fstab.
++ cat /etc/fstab |
++ grep -v '^#' |
++ while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do
++ if [ "$FSTAB_MP" = "$MP" ]; then
++ echo $FSTAB_FST
++ exit 0
++ fi
++ done
++}
++
++if [ $DO_REMOUNT_NOATIME -eq 1 ] ; then
++ NOATIME_OPT=",noatime"
++fi
++
++case "$1" in
++ start)
++ AGE=$((100*$MAX_AGE))
++ XFS_AGE=$(($XFS_HZ*$MAX_AGE))
++ echo -n "Starting laptop_mode"
++
++ if [ -d /proc/sys/vm/pagebuf ] ; then
++ # (For 2.4 and early 2.6.)
++ # This only needs to be set, not reset -- it is only used when
++ # laptop mode is enabled.
++ echo $XFS_AGE > /proc/sys/vm/pagebuf/lm_flush_age
++ echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
++ elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
++ # (A couple of early 2.6 laptop mode patches had these.)
++ # The same goes for these.
++ echo $XFS_AGE > /proc/sys/fs/xfs/lm_age_buffer
++ echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
++ elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
++ # (2.6.6)
++ # But not for these -- they are also used in normal
++ # operation.
++ echo $XFS_AGE > /proc/sys/fs/xfs/age_buffer
++ echo $XFS_AGE > /proc/sys/fs/xfs/sync_interval
++ elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
++ # (2.6.7 upwards)
++ # And not for these either. These are in centisecs,
++ # not USER_HZ, so we have to use $AGE, not $XFS_AGE.
++ echo $AGE > /proc/sys/fs/xfs/age_buffer_centisecs
++ echo $AGE > /proc/sys/fs/xfs/xfssyncd_centisecs
++ echo 3000 > /proc/sys/fs/xfs/xfsbufd_centisecs
++ fi
++
++ case "$KLEVEL" in
++ "2.4")
++ echo 1 > /proc/sys/vm/laptop_mode
++ echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush
++ ;;
++ "2.6")
++ echo 5 > /proc/sys/vm/laptop_mode
++ echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs
++ echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs
++ echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_ratio
++ echo "$DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio
++ ;;
++ esac
++ if [ $DO_REMOUNTS -eq 1 ]; then
++ cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
++ PARSEDOPTS="$(parse_mount_opts "$OPTS")"
++ if [ "$FST" = 'unknown' ]; then
++ FST=$(deduce_fstype $MP)
++ fi
++ case "$FST" in
++ "ext3"|"reiserfs")
++ PARSEDOPTS="$(parse_mount_opts commit "$OPTS")"
++ mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT
++ ;;
++ "xfs")
++ mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT
++ ;;
++ esac
++ if [ -b $DEV ] ; then
++ blockdev --setra $(($READAHEAD * 2)) $DEV
++ fi
++ done
++ fi
++ if [ $DO_HD -eq 1 ] ; then
++ for THISHD in $HD ; do
++ /sbin/hdparm -S $BATT_HD $THISHD > /dev/null 2>&1
++ /sbin/hdparm -B 1 $THISHD > /dev/null 2>&1
++ done
++ fi
++ if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
++ if [ $CPU_MAXFREQ = 'slowest' ]; then
++ CPU_MAXFREQ=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
++ fi
++ echo $CPU_MAXFREQ > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
++ fi
++ echo "."
++ ;;
++ stop)
++ U_AGE=$((100*$DEF_UPDATE))
++ B_AGE=$((100*$DEF_AGE))
++ echo -n "Stopping laptop_mode"
++ echo 0 > /proc/sys/vm/laptop_mode
++ if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
++ # These need to be restored, if there are no lm_*.
++ echo $(($XFS_HZ*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer
++ echo $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/sync_interval
++ elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
++ # These need to be restored as well.
++ echo $((100*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer_centisecs
++ echo $((100*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/xfssyncd_centisecs
++ echo $((100*$DEF_XFS_BUFD_INTERVAL)) > /proc/sys/fs/xfs/xfsbufd_centisecs
++ fi
++ case "$KLEVEL" in
++ "2.4")
++ echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush
++ ;;
++ "2.6")
++ echo "$U_AGE" > /proc/sys/vm/dirty_writeback_centisecs
++ echo "$B_AGE" > /proc/sys/vm/dirty_expire_centisecs
++ echo "$DEF_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio
++ echo "$DEF_DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio
++ ;;
++ esac
++ if [ $DO_REMOUNTS -eq 1 ] ; then
++ cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
++ # Reset commit and atime options to defaults.
++ if [ "$FST" = 'unknown' ]; then
++ FST=$(deduce_fstype $MP)
++ fi
++ case "$FST" in
++ "ext3"|"reiserfs")
++ PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)"
++ PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)"
++ mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
++ ;;
++ "xfs")
++ PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $OPTS)"
++ mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
++ ;;
++ esac
++ if [ -b $DEV ] ; then
++ blockdev --setra 256 $DEV
++ fi
++ done
++ fi
++ if [ $DO_HD -eq 1 ] ; then
++ for THISHD in $HD ; do
++ /sbin/hdparm -S $AC_HD $THISHD > /dev/null 2>&1
++ /sbin/hdparm -B 255 $THISHD > /dev/null 2>&1
++ done
++ fi
++ if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
++ echo `cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
++ fi
++ echo "."
++ ;;
++ *)
++ echo "Usage: $0 {start|stop}" 2>&1
++ exit 1
++ ;;
++
++esac
++
++exit 0
++--------------------CONTROL SCRIPT END------------------------------------------
++
++
++ACPI integration
++----------------
++
++Dax Kelson submitted this so that the ACPI acpid daemon will
++kick off the laptop_mode script and run hdparm. The part that
++automatically disables laptop mode when the battery is low was
++written by Jan Topinski.
++
++-----------------/etc/acpi/events/ac_adapter BEGIN------------------------------
++event=ac_adapter
++action=/etc/acpi/actions/ac.sh %e
++----------------/etc/acpi/events/ac_adapter END---------------------------------
++
++
++-----------------/etc/acpi/events/battery BEGIN---------------------------------
++event=battery.*
++action=/etc/acpi/actions/battery.sh %e
++----------------/etc/acpi/events/battery END------------------------------------
++
++
++----------------/etc/acpi/actions/ac.sh BEGIN-----------------------------------
++#!/bin/bash
++
++# ac on/offline event handler
++
++status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/$2/state`
++
++case $status in
++ "on-line")
++ /sbin/laptop_mode stop
++ exit 0
++ ;;
++ "off-line")
++ /sbin/laptop_mode start
++ exit 0
++ ;;
++esac
++---------------------------/etc/acpi/actions/ac.sh END--------------------------
++
++
++---------------------------/etc/acpi/actions/battery.sh BEGIN-------------------
++#! /bin/bash
++
++# Automatically disable laptop mode when the battery almost runs out.
++
++BATT_INFO=/proc/acpi/battery/$2/state
++
++if [[ -f /proc/sys/vm/laptop_mode ]]
++then
++ LM=`cat /proc/sys/vm/laptop_mode`
++ if [[ $LM -gt 0 ]]
++ then
++ if [[ -f $BATT_INFO ]]
++ then
++ # Source the config file only now that we know we need
++ if [ -f /etc/default/laptop-mode ] ; then
++ # Debian
++ . /etc/default/laptop-mode
++ elif [ -f /etc/sysconfig/laptop-mode ] ; then
++ # Others
++ . /etc/sysconfig/laptop-mode
++ fi
++ MINIMUM_BATTERY_MINUTES=${MINIMUM_BATTERY_MINUTES:-'10'}
++
++ ACTION="`cat $BATT_INFO | grep charging | cut -c 26-`"
++ if [[ ACTION -eq "discharging" ]]
++ then
++ PRESENT_RATE=`cat $BATT_INFO | grep "present rate:" | sed "s/.* \([0-9][0-9]* \).*/\1/" `
++ REMAINING=`cat $BATT_INFO | grep "remaining capacity:" | sed "s/.* \([0-9][0-9]* \).*/\1/" `
++ fi
++ if (($REMAINING * 60 / $PRESENT_RATE < $MINIMUM_BATTERY_MINUTES))
++ then
++ /sbin/laptop_mode stop
++ fi
++ else
++ logger -p daemon.warning "You are using laptop mode and your battery interface $BATT_INFO is missing. This may lead to loss of data when the battery runs out. Check kernel ACPI support and /proc/acpi/battery folder, and edit /etc/acpi/battery.sh to set BATT_INFO to the correct path."
++ fi
++ fi
++fi
++---------------------------/etc/acpi/actions/battery.sh END--------------------
++
++
++Monitoring tool
++---------------
++
++Bartek Kania submitted this, it can be used to measure how much time your disk
++spends spun up/down.
++
++---------------------------dslm.c BEGIN-----------------------------------------
++/*
++ * Simple Disk Sleep Monitor
++ * by Bartek Kania
++ * Licenced under the GPL
++ */
++#include <unistd.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <time.h>
++#include <string.h>
++#include <signal.h>
++#include <sys/ioctl.h>
++#include <linux/hdreg.h>
++
++#ifdef DEBUG
++#define D(x) x
++#else
++#define D(x)
++#endif
++
++int endit = 0;
++
++/* Check if the disk is in powersave-mode
++ * Most of the code is stolen from hdparm.
++ * 1 = active, 0 = standby/sleep, -1 = unknown */
++int check_powermode(int fd)
++{
++ unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
++ int state;
++
++ if (ioctl(fd, HDIO_DRIVE_CMD, &args)
++ && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
++ && ioctl(fd, HDIO_DRIVE_CMD, &args)) {
++ if (errno != EIO || args[0] != 0 || args[1] != 0) {
++ state = -1; /* "unknown"; */
++ } else
++ state = 0; /* "sleeping"; */
++ } else {
++ state = (args[2] == 255) ? 1 : 0;
++ }
++ D(printf(" drive state is: %d\n", state));
++
++ return state;
++}
++
++char *state_name(int i)
++{
++ if (i == -1) return "unknown";
++ if (i == 0) return "sleeping";
++ if (i == 1) return "active";
++
++ return "internal error";
++}
++
++char *myctime(time_t time)
++{
++ char *ts = ctime(&time);
++ ts[strlen(ts) - 1] = 0;
++
++ return ts;
++}
++
++void measure(int fd)
++{
++ time_t start_time;
++ int last_state;
++ time_t last_time;
++ int curr_state;
++ time_t curr_time = 0;
++ time_t time_diff;
++ time_t active_time = 0;
++ time_t sleep_time = 0;
++ time_t unknown_time = 0;
++ time_t total_time = 0;
++ int changes = 0;
++ float tmp;
++
++ printf("Starting measurements\n");
++
++ last_state = check_powermode(fd);
++ start_time = last_time = time(0);
++ printf(" System is in state %s\n\n", state_name(last_state));
++
++ while(!endit) {
++ sleep(1);
++ curr_state = check_powermode(fd);
++
++ if (curr_state != last_state || endit) {
++ changes++;
++ curr_time = time(0);
++ time_diff = curr_time - last_time;
++
++ if (last_state == 1) active_time += time_diff;
++ else if (last_state == 0) sleep_time += time_diff;
++ else unknown_time += time_diff;
++
++ last_state = curr_state;
++ last_time = curr_time;
++
++ printf("%s: State-change to %s\n", myctime(curr_time),
++ state_name(curr_state));
++ }
++ }
++ changes--; /* Compensate for SIGINT */
++
++ total_time = time(0) - start_time;
++ printf("\nTotal running time: %lus\n", curr_time - start_time);
++ printf(" State changed %d times\n", changes);
++
++ tmp = (float)sleep_time / (float)total_time * 100;
++ printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp);
++ tmp = (float)active_time / (float)total_time * 100;
++ printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp);
++ tmp = (float)unknown_time / (float)total_time * 100;
++ printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
++}
++
++void ender(int s)
++{
++ endit = 1;
++}
++
++void usage()
++{
++ puts("usage: dslm [-w <time>] <disk>");
++ exit(0);
++}
++
++int main(int argc, char **argv)
++{
++ int fd;
++ char *disk = 0;
++ int settle_time = 60;
++
++ /* Parse the simple command-line */
++ if (argc == 2)
++ disk = argv[1];
++ else if (argc == 4) {
++ settle_time = atoi(argv[2]);
++ disk = argv[3];
++ } else
++ usage();
++
++ if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
++ printf("Can't open %s, because: %s\n", disk, strerror(errno));
++ exit(-1);
++ }
++
++ if (settle_time) {
++ printf("Waiting %d seconds for the system to settle down to "
++ "'normal'\n", settle_time);
++ sleep(settle_time);
++ } else
++ puts("Not waiting for system to settle down");
++
++ signal(SIGINT, ender);
++
++ measure(fd);
++
++ close(fd);
++
++ return 0;
++}
++---------------------------dslm.c END-------------------------------------------
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 0f23d67..bec5a32 100644
--- a/Documentation/lguest/lguest.c
@@ -39,6 +2045,1029 @@
o The probe() and remove() functions should be marked __devinit
and __devexit respectively. All initialization functions
+diff --git a/Documentation/pm.txt b/Documentation/pm.txt
+deleted file mode 100644
+index da8589a..0000000
+--- a/Documentation/pm.txt
++++ /dev/null
+@@ -1,257 +0,0 @@
+- Linux Power Management Support
+-
+-This document briefly describes how to use power management with your
+-Linux system and how to add power management support to Linux drivers.
+-
+-APM or ACPI?
+-------------
+-If you have a relatively recent x86 mobile, desktop, or server system,
+-odds are it supports either Advanced Power Management (APM) or
+-Advanced Configuration and Power Interface (ACPI). ACPI is the newer
+-of the two technologies and puts power management in the hands of the
+-operating system, allowing for more intelligent power management than
+-is possible with BIOS controlled APM.
+-
+-The best way to determine which, if either, your system supports is to
+-build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
+-enabled by default). If a working ACPI implementation is found, the
+-ACPI driver will override and disable APM, otherwise the APM driver
+-will be used.
+-
+-No, sorry, you cannot have both ACPI and APM enabled and running at
+-once. Some people with broken ACPI or broken APM implementations
+-would like to use both to get a full set of working features, but you
+-simply cannot mix and match the two. Only one power management
+-interface can be in control of the machine at once. Think about it..
+-
+-User-space Daemons
+-------------------
+-Both APM and ACPI rely on user-space daemons, apmd and acpid
+-respectively, to be completely functional. Obtain both of these
+-daemons from your Linux distribution or from the Internet (see below)
+-and be sure that they are started sometime in the system boot process.
+-Go ahead and start both. If ACPI or APM is not available on your
+-system the associated daemon will exit gracefully.
+-
+- apmd: http://worldvisions.ca/~apenwarr/apmd/
+- acpid: http://acpid.sf.net/
+-
+-Driver Interface -- OBSOLETE, DO NOT USE!
+-----------------*************************
+-
+-Note: pm_register(), pm_access(), pm_dev_idle() and friends are
+-obsolete. Please do not use them. Instead you should properly hook
+-your driver into the driver model, and use its suspend()/resume()
+-callbacks to do this kind of stuff.
+-
+-If you are writing a new driver or maintaining an old driver, it
+-should include power management support. Without power management
+-support, a single driver may prevent a system with power management
+-capabilities from ever being able to suspend (safely).
+-
+-Overview:
+-1) Register each instance of a device with "pm_register"
+-2) Call "pm_access" before accessing the hardware.
+- (this will ensure that the hardware is awake and ready)
+-3) Your "pm_callback" is called before going into a
+- suspend state (ACPI D1-D3) or after resuming (ACPI D0)
+- from a suspend.
+-4) Call "pm_dev_idle" when the device is not being used
+- (optional but will improve device idle detection)
+-5) When unloaded, unregister the device with "pm_unregister"
+-
+-/*
+- * Description: Register a device with the power-management subsystem
+- *
+- * Parameters:
+- * type - device type (PCI device, system device, ...)
+- * id - instance number or unique identifier
+- * cback - request handler callback (suspend, resume, ...)
+- *
+- * Returns: Registered PM device or NULL on error
+- *
+- * Examples:
+- * dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback);
+- *
+- * struct pci_dev *pci_dev = pci_find_dev(...);
+- * dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback);
+- */
+-struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback);
+-
+-/*
+- * Description: Unregister a device with the power management subsystem
+- *
+- * Parameters:
+- * dev - PM device previously returned from pm_register
+- */
+-void pm_unregister(struct pm_dev *dev);
+-
+-/*
+- * Description: Unregister all devices with a matching callback function
+- *
+- * Parameters:
+- * cback - previously registered request callback
+- *
+- * Notes: Provided for easier porting from old APM interface
+- */
+-void pm_unregister_all(pm_callback cback);
+-
+-/*
+- * Power management request callback
+- *
+- * Parameters:
+- * dev - PM device previously returned from pm_register
+- * rqst - request type
+- * data - data, if any, associated with the request
+- *
+- * Returns: 0 if the request is successful
+- * EINVAL if the request is not supported
+- * EBUSY if the device is now busy and cannot handle the request
+- * ENOMEM if the device was unable to handle the request due to memory
+- *
+- * Details: The device request callback will be called before the
+- * device/system enters a suspend state (ACPI D1-D3) or
+- * or after the device/system resumes from suspend (ACPI D0).
+- * For PM_SUSPEND, the ACPI D-state being entered is passed
+- * as the "data" argument to the callback. The device
+- * driver should save (PM_SUSPEND) or restore (PM_RESUME)
+- * device context when the request callback is called.
+- *
+- * Once a driver returns 0 (success) from a suspend
+- * request, it should not process any further requests or
+- * access the device hardware until a call to "pm_access" is made.
+- */
+-typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
+-
+-Driver Details
+---------------
+-This is just a quick Q&A as a stopgap until a real driver writers'
+-power management guide is available.
+-
+-Q: When is a device suspended?
+-
+-Devices can be suspended based on direct user request (eg. laptop lid
+-closes), system power policy (eg. sleep after 30 minutes of console
+-inactivity), or device power policy (eg. power down device after 5
+-minutes of inactivity)
+-
+-Q: Must a driver honor a suspend request?
+-
+-No, a driver can return -EBUSY from a suspend request and this
+-will stop the system from suspending. When a suspend request
+-fails, all suspended devices are resumed and the system continues
+-to run. Suspend can be retried at a later time.
+-
+-Q: Can the driver block suspend/resume requests?
+-
+-Yes, a driver can delay its return from a suspend or resume
+-request until the device is ready to handle requests. It
+-is advantageous to return as quickly as possible from a
+-request as suspend/resume are done serially.
+-
+-Q: What context is a suspend/resume initiated from?
+-
+-A suspend or resume is initiated from a kernel thread context.
+-It is safe to block, allocate memory, initiate requests
+-or anything else you can do within the kernel.
+-
+-Q: Will requests continue to arrive after a suspend?
+-
+-Possibly. It is the driver's responsibility to queue(*),
+-fail, or drop any requests that arrive after returning
+-success to a suspend request. It is important that the
+-driver not access its device until after it receives
+-a resume request as the device's bus may no longer
+-be active.
+-
+-(*) If a driver queues requests for processing after
+- resume be aware that the device, network, etc.
+- might be in a different state than at suspend time.
+- It's probably better to drop requests unless
+- the driver is a storage device.
+-
+-Q: Do I have to manage bus-specific power management registers
+-
+-No. It is the responsibility of the bus driver to manage
+-PCI, USB, etc. power management registers. The bus driver
+-or the power management subsystem will also enable any
+-wake-on functionality that the device has.
+-
+-Q: So, really, what do I need to do to support suspend/resume?
+-
+-You need to save any device context that would
+-be lost if the device was powered off and then restore
+-it at resume time. When ACPI is active, there are
+-three levels of device suspend states; D1, D2, and D3.
+-(The suspend state is passed as the "data" argument
+-to the device callback.) With D3, the device is powered
+-off and loses all context, D1 and D2 are shallower power
+-states and require less device context to be saved. To
+-play it safe, just save everything at suspend and restore
+-everything at resume.
+-
+-Q: Where do I store device context for suspend?
+-
+-Anywhere in memory, kmalloc a buffer or store it
+-in the device descriptor. You are guaranteed that the
+-contents of memory will be restored and accessible
+-before resume, even when the system suspends to disk.
+-
+-Q: What do I need to do for ACPI vs. APM vs. etc?
+-
+-Drivers need not be aware of the specific power management
+-technology that is active. They just need to be aware
+-of when the overlying power management system requests
+-that they suspend or resume.
+-
+-Q: What about device dependencies?
+-
+-When a driver registers a device, the power management
+-subsystem uses the information provided to build a
+-tree of device dependencies (eg. USB device X is on
+-USB controller Y which is on PCI bus Z) When power
+-management wants to suspend a device, it first sends
+-a suspend request to its driver, then the bus driver,
+-and so on up to the system bus. Device resumes
+-proceed in the opposite direction.
+-
+-Q: Who do I contact for additional information about
+- enabling power management for my specific driver/device?
+-
+-ACPI Development mailing list: linux-acpi at vger.kernel.org
+-
+-System Interface -- OBSOLETE, DO NOT USE!
+-----------------*************************
+-If you are providing new power management support to Linux (ie.
+-adding support for something like APM or ACPI), you should
+-communicate with drivers through the existing generic power
+-management interface.
+-
+-/*
+- * Send a request to all devices
+- *
+- * Parameters:
+- * rqst - request type
+- * data - data, if any, associated with the request
+- *
+- * Returns: 0 if the request is successful
+- * See "pm_callback" return for errors
+- *
+- * Details: Walk list of registered devices and call pm_send
+- * for each until complete or an error is encountered.
+- * If an error is encountered for a suspend request,
+- * return all devices to the state they were in before
+- * the suspend request.
+- */
+-int pm_send_all(pm_request_t rqst, void *data);
+-
+-/*
+- * Find a matching device
+- *
+- * Parameters:
+- * type - device type (PCI device, system device, or 0 to match all devices)
+- * from - previous match or NULL to start from the beginning
+- *
+- * Returns: Matching device or NULL if none found
+- */
+-struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
+diff --git a/Documentation/pm_qos_interface.txt b/Documentation/pm_qos_interface.txt
+deleted file mode 100644
+index 49adb1a..0000000
+--- a/Documentation/pm_qos_interface.txt
++++ /dev/null
+@@ -1,59 +0,0 @@
+-PM quality of Service interface.
+-
+-This interface provides a kernel and user mode interface for registering
+-performance expectations by drivers, subsystems and user space applications on
+-one of the parameters.
+-
+-Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
+-initial set of pm_qos parameters.
+-
+-The infrastructure exposes multiple misc device nodes one per implemented
+-parameter. The set of parameters implement is defined by pm_qos_power_init()
+-and pm_qos_params.h. This is done because having the available parameters
+-being runtime configurable or changeable from a driver was seen as too easy to
+-abuse.
+-
+-For each parameter a list of performance requirements is maintained along with
+-an aggregated target value. The aggregated target value is updated with
+-changes to the requirement list or elements of the list. Typically the
+-aggregated target value is simply the max or min of the requirement values held
+-in the parameter list elements.
+-
+-From kernel mode the use of this interface is simple:
+-pm_qos_add_requirement(param_id, name, target_value):
+-Will insert a named element in the list for that identified PM_QOS parameter
+-with the target value. Upon change to this list the new target is recomputed
+-and any registered notifiers are called only if the target value is now
+-different.
+-
+-pm_qos_update_requirement(param_id, name, new_target_value):
+-Will search the list identified by the param_id for the named list element and
+-then update its target value, calling the notification tree if the aggregated
+-target is changed. with that name is already registered.
+-
+-pm_qos_remove_requirement(param_id, name):
+-Will search the identified list for the named element and remove it, after
+-removal it will update the aggregate target and call the notification tree if
+-the target was changed as a result of removing the named requirement.
+-
+-
+-From user mode:
+-Only processes can register a pm_qos requirement. To provide for automatic
+-cleanup for process the interface requires the process to register its
+-parameter requirements in the following way:
+-
+-To register the default pm_qos target for the specific parameter, the process
+-must open one of /dev/[cpu_dma_latency, network_latency, network_throughput]
+-
+-As long as the device node is held open that process has a registered
+-requirement on the parameter. The name of the requirement is "process_<PID>"
+-derived from the current->pid from within the open system call.
+-
+-To change the requested target value the process needs to write a s32 value to
+-the open device node. This translates to a pm_qos_update_requirement call.
+-
+-To remove the user mode request for a target value simply close the device
+-node.
+-
+-
+-
+diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
+index 8db4e41..a55d7f1 100644
+--- a/Documentation/power/00-INDEX
++++ b/Documentation/power/00-INDEX
+@@ -14,6 +14,12 @@ notifiers.txt
+ - Registering suspend notifiers in device drivers
+ pci.txt
+ - How the PCI Subsystem Does Power Management
++pm.txt
++ - info on Linux power management support.
++pm_qos_interface.txt
++ - info on Linux PM Quality of Service interface
++power_supply_class.txt
++ - Tells userspace about battery, UPS, AC or DC power supply properties
+ s2ram.txt
+ - How to get suspend to ram working (and debug it when it isn't)
+ states.txt
+diff --git a/Documentation/power/pm.txt b/Documentation/power/pm.txt
+new file mode 100644
+index 0000000..be84150
+--- /dev/null
++++ b/Documentation/power/pm.txt
+@@ -0,0 +1,257 @@
++ Linux Power Management Support
++
++This document briefly describes how to use power management with your
++Linux system and how to add power management support to Linux drivers.
++
++APM or ACPI?
++------------
++If you have a relatively recent x86 mobile, desktop, or server system,
++odds are it supports either Advanced Power Management (APM) or
++Advanced Configuration and Power Interface (ACPI). ACPI is the newer
++of the two technologies and puts power management in the hands of the
++operating system, allowing for more intelligent power management than
++is possible with BIOS controlled APM.
++
++The best way to determine which, if either, your system supports is to
++build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
++enabled by default). If a working ACPI implementation is found, the
++ACPI driver will override and disable APM, otherwise the APM driver
++will be used.
++
++No, sorry, you cannot have both ACPI and APM enabled and running at
++once. Some people with broken ACPI or broken APM implementations
++would like to use both to get a full set of working features, but you
++simply cannot mix and match the two. Only one power management
++interface can be in control of the machine at once. Think about it..
++
++User-space Daemons
++------------------
++Both APM and ACPI rely on user-space daemons, apmd and acpid
++respectively, to be completely functional. Obtain both of these
++daemons from your Linux distribution or from the Internet (see below)
++and be sure that they are started sometime in the system boot process.
++Go ahead and start both. If ACPI or APM is not available on your
++system the associated daemon will exit gracefully.
++
++ apmd: http://worldvisions.ca/~apenwarr/apmd/
++ acpid: http://acpid.sf.net/
++
++Driver Interface -- OBSOLETE, DO NOT USE!
++----------------*************************
++
++Note: pm_register(), pm_access(), pm_dev_idle() and friends are
++obsolete. Please do not use them. Instead you should properly hook
++your driver into the driver model, and use its suspend()/resume()
++callbacks to do this kind of stuff.
++
++If you are writing a new driver or maintaining an old driver, it
++should include power management support. Without power management
++support, a single driver may prevent a system with power management
++capabilities from ever being able to suspend (safely).
++
++Overview:
++1) Register each instance of a device with "pm_register"
++2) Call "pm_access" before accessing the hardware.
++ (this will ensure that the hardware is awake and ready)
++3) Your "pm_callback" is called before going into a
++ suspend state (ACPI D1-D3) or after resuming (ACPI D0)
++ from a suspend.
++4) Call "pm_dev_idle" when the device is not being used
++ (optional but will improve device idle detection)
++5) When unloaded, unregister the device with "pm_unregister"
++
++/*
++ * Description: Register a device with the power-management subsystem
++ *
++ * Parameters:
++ * type - device type (PCI device, system device, ...)
++ * id - instance number or unique identifier
++ * cback - request handler callback (suspend, resume, ...)
++ *
++ * Returns: Registered PM device or NULL on error
++ *
++ * Examples:
++ * dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback);
++ *
++ * struct pci_dev *pci_dev = pci_find_dev(...);
++ * dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback);
++ */
++struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback);
++
++/*
++ * Description: Unregister a device with the power management subsystem
++ *
++ * Parameters:
++ * dev - PM device previously returned from pm_register
++ */
++void pm_unregister(struct pm_dev *dev);
++
++/*
++ * Description: Unregister all devices with a matching callback function
++ *
++ * Parameters:
++ * cback - previously registered request callback
++ *
++ * Notes: Provided for easier porting from old APM interface
++ */
++void pm_unregister_all(pm_callback cback);
++
++/*
++ * Power management request callback
++ *
++ * Parameters:
++ * dev - PM device previously returned from pm_register
++ * rqst - request type
++ * data - data, if any, associated with the request
++ *
++ * Returns: 0 if the request is successful
++ * EINVAL if the request is not supported
++ * EBUSY if the device is now busy and cannot handle the request
++ * ENOMEM if the device was unable to handle the request due to memory
++ *
++ * Details: The device request callback will be called before the
++ * device/system enters a suspend state (ACPI D1-D3) or
++ * or after the device/system resumes from suspend (ACPI D0).
++ * For PM_SUSPEND, the ACPI D-state being entered is passed
++ * as the "data" argument to the callback. The device
++ * driver should save (PM_SUSPEND) or restore (PM_RESUME)
++ * device context when the request callback is called.
++ *
++ * Once a driver returns 0 (success) from a suspend
++ * request, it should not process any further requests or
++ * access the device hardware until a call to "pm_access" is made.
++ */
++typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
++
++Driver Details
++--------------
++This is just a quick Q&A as a stopgap until a real driver writers'
++power management guide is available.
++
++Q: When is a device suspended?
++
++Devices can be suspended based on direct user request (eg. laptop lid
++closes), system power policy (eg. sleep after 30 minutes of console
++inactivity), or device power policy (eg. power down device after 5
++minutes of inactivity)
++
++Q: Must a driver honor a suspend request?
++
++No, a driver can return -EBUSY from a suspend request and this
++will stop the system from suspending. When a suspend request
++fails, all suspended devices are resumed and the system continues
++to run. Suspend can be retried at a later time.
++
++Q: Can the driver block suspend/resume requests?
++
++Yes, a driver can delay its return from a suspend or resume
++request until the device is ready to handle requests. It
++is advantageous to return as quickly as possible from a
++request as suspend/resume are done serially.
++
++Q: What context is a suspend/resume initiated from?
++
++A suspend or resume is initiated from a kernel thread context.
++It is safe to block, allocate memory, initiate requests
++or anything else you can do within the kernel.
++
++Q: Will requests continue to arrive after a suspend?
++
++Possibly. It is the driver's responsibility to queue(*),
++fail, or drop any requests that arrive after returning
++success to a suspend request. It is important that the
++driver not access its device until after it receives
++a resume request as the device's bus may no longer
++be active.
++
++(*) If a driver queues requests for processing after
++ resume be aware that the device, network, etc.
++ might be in a different state than at suspend time.
++ It's probably better to drop requests unless
++ the driver is a storage device.
++
++Q: Do I have to manage bus-specific power management registers
++
++No. It is the responsibility of the bus driver to manage
++PCI, USB, etc. power management registers. The bus driver
++or the power management subsystem will also enable any
++wake-on functionality that the device has.
++
++Q: So, really, what do I need to do to support suspend/resume?
++
++You need to save any device context that would
++be lost if the device was powered off and then restore
++it at resume time. When ACPI is active, there are
++three levels of device suspend states; D1, D2, and D3.
++(The suspend state is passed as the "data" argument
++to the device callback.) With D3, the device is powered
++off and loses all context, D1 and D2 are shallower power
++states and require less device context to be saved. To
++play it safe, just save everything at suspend and restore
++everything at resume.
++
++Q: Where do I store device context for suspend?
++
++Anywhere in memory, kmalloc a buffer or store it
++in the device descriptor. You are guaranteed that the
++contents of memory will be restored and accessible
++before resume, even when the system suspends to disk.
++
++Q: What do I need to do for ACPI vs. APM vs. etc?
++
++Drivers need not be aware of the specific power management
++technology that is active. They just need to be aware
++of when the overlying power management system requests
++that they suspend or resume.
++
++Q: What about device dependencies?
++
++When a driver registers a device, the power management
++subsystem uses the information provided to build a
++tree of device dependencies (eg. USB device X is on
++USB controller Y which is on PCI bus Z) When power
++management wants to suspend a device, it first sends
++a suspend request to its driver, then the bus driver,
++and so on up to the system bus. Device resumes
++proceed in the opposite direction.
++
++Q: Who do I contact for additional information about
++ enabling power management for my specific driver/device?
++
++ACPI Development mailing list: linux-acpi at vger.kernel.org
++
++System Interface -- OBSOLETE, DO NOT USE!
++----------------*************************
++If you are providing new power management support to Linux (ie.
++adding support for something like APM or ACPI), you should
++communicate with drivers through the existing generic power
++management interface.
++
++/*
++ * Send a request to all devices
++ *
++ * Parameters:
++ * rqst - request type
++ * data - data, if any, associated with the request
++ *
++ * Returns: 0 if the request is successful
++ * See "pm_callback" return for errors
++ *
++ * Details: Walk list of registered devices and call pm_send
++ * for each until complete or an error is encountered.
++ * If an error is encountered for a suspend request,
++ * return all devices to the state they were in before
++ * the suspend request.
++ */
++int pm_send_all(pm_request_t rqst, void *data);
++
++/*
++ * Find a matching device
++ *
++ * Parameters:
++ * type - device type (PCI device, system device, or 0 to match all devices)
++ * from - previous match or NULL to start from the beginning
++ *
++ * Returns: Matching device or NULL if none found
++ */
++struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
+diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
+new file mode 100644
+index 0000000..49adb1a
+--- /dev/null
++++ b/Documentation/power/pm_qos_interface.txt
+@@ -0,0 +1,59 @@
++PM quality of Service interface.
++
++This interface provides a kernel and user mode interface for registering
++performance expectations by drivers, subsystems and user space applications on
++one of the parameters.
++
++Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
++initial set of pm_qos parameters.
++
++The infrastructure exposes multiple misc device nodes one per implemented
++parameter. The set of parameters implement is defined by pm_qos_power_init()
++and pm_qos_params.h. This is done because having the available parameters
++being runtime configurable or changeable from a driver was seen as too easy to
++abuse.
++
++For each parameter a list of performance requirements is maintained along with
++an aggregated target value. The aggregated target value is updated with
++changes to the requirement list or elements of the list. Typically the
++aggregated target value is simply the max or min of the requirement values held
++in the parameter list elements.
++
++From kernel mode the use of this interface is simple:
++pm_qos_add_requirement(param_id, name, target_value):
++Will insert a named element in the list for that identified PM_QOS parameter
++with the target value. Upon change to this list the new target is recomputed
++and any registered notifiers are called only if the target value is now
++different.
++
++pm_qos_update_requirement(param_id, name, new_target_value):
++Will search the list identified by the param_id for the named list element and
++then update its target value, calling the notification tree if the aggregated
++target is changed. with that name is already registered.
++
++pm_qos_remove_requirement(param_id, name):
++Will search the identified list for the named element and remove it, after
++removal it will update the aggregate target and call the notification tree if
++the target was changed as a result of removing the named requirement.
++
++
++From user mode:
++Only processes can register a pm_qos requirement. To provide for automatic
++cleanup for process the interface requires the process to register its
++parameter requirements in the following way:
++
++To register the default pm_qos target for the specific parameter, the process
++must open one of /dev/[cpu_dma_latency, network_latency, network_throughput]
++
++As long as the device node is held open that process has a registered
++requirement on the parameter. The name of the requirement is "process_<PID>"
++derived from the current->pid from within the open system call.
++
++To change the requested target value the process needs to write a s32 value to
++the open device node. This translates to a pm_qos_update_requirement call.
++
++To remove the user mode request for a target value simply close the device
++node.
++
++
++
+diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
+new file mode 100644
+index 0000000..a8686e5
+--- /dev/null
++++ b/Documentation/power/power_supply_class.txt
+@@ -0,0 +1,169 @@
++Linux power supply class
++========================
++
++Synopsis
++~~~~~~~~
++Power supply class used to represent battery, UPS, AC or DC power supply
++properties to user-space.
++
++It defines core set of attributes, which should be applicable to (almost)
++every power supply out there. Attributes are available via sysfs and uevent
++interfaces.
++
++Each attribute has well defined meaning, up to unit of measure used. While
++the attributes provided are believed to be universally applicable to any
++power supply, specific monitoring hardware may not be able to provide them
++all, so any of them may be skipped.
++
++Power supply class is extensible, and allows to define drivers own attributes.
++The core attribute set is subject to the standard Linux evolution (i.e.
++if it will be found that some attribute is applicable to many power supply
++types or their drivers, it can be added to the core set).
++
++It also integrates with LED framework, for the purpose of providing
++typically expected feedback of battery charging/fully charged status and
++AC/USB power supply online status. (Note that specific details of the
++indication (including whether to use it at all) are fully controllable by
++user and/or specific machine defaults, per design principles of LED
++framework).
++
++
++Attributes/properties
++~~~~~~~~~~~~~~~~~~~~~
++Power supply class has predefined set of attributes, this eliminates code
++duplication across drivers. Power supply class insist on reusing its
++predefined attributes *and* their units.
++
++So, userspace gets predictable set of attributes and their units for any
++kind of power supply, and can process/present them to a user in consistent
++manner. Results for different power supplies and machines are also directly
++comparable.
++
++See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
++example how to declare and handle attributes.
++
++
++Units
++~~~~~
++Quoting include/linux/power_supply.h:
++
++ All voltages, currents, charges, energies, time and temperatures in µV,
++ µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
++ stated. It's driver's job to convert its raw values to units in which
++ this class operates.
++
++
++Attributes/properties detailed
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++~ ~ ~ ~ ~ ~ ~ Charge/Energy/Capacity - how to not confuse ~ ~ ~ ~ ~ ~ ~
++~ ~
++~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity" ~
++~ of battery, this class distinguish these terms. Don't mix them! ~
++~ ~
++~ CHARGE_* attributes represents capacity in µAh only. ~
++~ ENERGY_* attributes represents capacity in µWh only. ~
++~ CAPACITY attribute represents capacity in *percents*, from 0 to 100. ~
++~ ~
++~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
++
++Postfixes:
++_AVG - *hardware* averaged value, use it if your hardware is really able to
++report averaged values.
++_NOW - momentary/instantaneous values.
++
++STATUS - this attribute represents operating status (charging, full,
++discharging (i.e. powering a load), etc.). This corresponds to
++BATTERY_STATUS_* values, as defined in battery.h.
++
++HEALTH - represents health of the battery, values corresponds to
++POWER_SUPPLY_HEALTH_*, defined in battery.h.
++
++VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
++minimal power supply voltages. Maximal/minimal means values of voltages
++when battery considered "full"/"empty" at normal conditions. Yes, there is
++no direct relation between voltage and battery capacity, but some dumb
++batteries use voltage for very approximated calculation of capacity.
++Battery driver also can use this attribute just to inform userspace
++about maximal and minimal voltage thresholds of a given battery.
++
++VOLTAGE_MAX, VOLTAGE_MIN - same as _DESIGN voltage values except that
++these ones should be used if hardware could only guess (measure and
++retain) the thresholds of a given power supply.
++
++CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
++battery considered full/empty.
++
++ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
++
++CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
++of charge when battery became full/empty". It also could mean "value of
++charge when battery considered full/empty at given conditions (temperature,
++age)". I.e. these attributes represents real thresholds, not design values.
++
++ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
++
++CAPACITY - capacity in percents.
++
++TEMP - temperature of the power supply.
++TEMP_AMBIENT - ambient temperature.
++
++TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
++while battery powers a load)
++TIME_TO_FULL - seconds left for battery to be considered full (i.e.
++while battery is charging)
++
++
++Battery <-> external power supply interaction
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Often power supplies are acting as supplies and supplicants at the same
++time. Batteries are good example. So, batteries usually care if they're
++externally powered or not.
++
++For that case, power supply class implements notification mechanism for
++batteries.
++
++External power supply (AC) lists supplicants (batteries) names in
++"supplied_to" struct member, and each power_supply_changed() call
++issued by external power supply will notify supplicants via
++external_power_changed callback.
++
++
++QA
++~~
++Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
++A: If you cannot find attribute suitable for your driver needs, feel free
++ to add it and send patch along with your driver.
++
++ The attributes available currently are the ones currently provided by the
++ drivers written.
++
++ Good candidates to add in future: model/part#, cycle_time, manufacturer,
++ etc.
++
++
++Q: I have some very specific attribute (e.g. battery color), should I add
++ this attribute to standard ones?
++A: Most likely, no. Such attribute can be placed in the driver itself, if
++ it is useful. Of course, if the attribute in question applicable to
++ large set of batteries, provided by many drivers, and/or comes from
++ some general battery specification/standard, it may be a candidate to
++ be added to the core attribute set.
++
++
++Q: Suppose, my battery monitoring chip/firmware does not provides capacity
++ in percents, but provides charge_{now,full,empty}. Should I calculate
++ percentage capacity manually, inside the driver, and register CAPACITY
++ attribute? The same question about time_to_empty/time_to_full.
++A: Most likely, no. This class is designed to export properties which are
++ directly measurable by the specific hardware available.
++
++ Inferring not available properties using some heuristics or mathematical
++ model is not subject of work for a battery driver. Such functionality
++ should be factored out, and in fact, apm_power, the driver to serve
++ legacy APM API on top of power supply class, uses a simple heuristic of
++ approximating remaining battery capacity based on its charge, current,
++ voltage and so on. But full-fledged battery model is likely not subject
++ for kernel at all, as it would require floating point calculation to deal
++ with things like differential equations and Kalman filters. This is
++ better be handled by batteryd/libbattery, yet to be written.
+diff --git a/Documentation/power_supply_class.txt b/Documentation/power_supply_class.txt
+deleted file mode 100644
+index a8686e5..0000000
+--- a/Documentation/power_supply_class.txt
++++ /dev/null
+@@ -1,169 +0,0 @@
+-Linux power supply class
+-========================
+-
+-Synopsis
+-~~~~~~~~
+-Power supply class used to represent battery, UPS, AC or DC power supply
+-properties to user-space.
+-
+-It defines core set of attributes, which should be applicable to (almost)
+-every power supply out there. Attributes are available via sysfs and uevent
+-interfaces.
+-
+-Each attribute has well defined meaning, up to unit of measure used. While
+-the attributes provided are believed to be universally applicable to any
+-power supply, specific monitoring hardware may not be able to provide them
+-all, so any of them may be skipped.
+-
+-Power supply class is extensible, and allows to define drivers own attributes.
+-The core attribute set is subject to the standard Linux evolution (i.e.
+-if it will be found that some attribute is applicable to many power supply
+-types or their drivers, it can be added to the core set).
+-
+-It also integrates with LED framework, for the purpose of providing
+-typically expected feedback of battery charging/fully charged status and
+-AC/USB power supply online status. (Note that specific details of the
+-indication (including whether to use it at all) are fully controllable by
+-user and/or specific machine defaults, per design principles of LED
+-framework).
+-
+-
+-Attributes/properties
+-~~~~~~~~~~~~~~~~~~~~~
+-Power supply class has predefined set of attributes, this eliminates code
+-duplication across drivers. Power supply class insist on reusing its
+-predefined attributes *and* their units.
+-
+-So, userspace gets predictable set of attributes and their units for any
+-kind of power supply, and can process/present them to a user in consistent
+-manner. Results for different power supplies and machines are also directly
+-comparable.
+-
+-See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
+-example how to declare and handle attributes.
+-
+-
+-Units
+-~~~~~
+-Quoting include/linux/power_supply.h:
+-
+- All voltages, currents, charges, energies, time and temperatures in µV,
+- µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+- stated. It's driver's job to convert its raw values to units in which
+- this class operates.
+-
+-
+-Attributes/properties detailed
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-~ ~ ~ ~ ~ ~ ~ Charge/Energy/Capacity - how to not confuse ~ ~ ~ ~ ~ ~ ~
+-~ ~
+-~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity" ~
+-~ of battery, this class distinguish these terms. Don't mix them! ~
+-~ ~
+-~ CHARGE_* attributes represents capacity in µAh only. ~
+-~ ENERGY_* attributes represents capacity in µWh only. ~
+-~ CAPACITY attribute represents capacity in *percents*, from 0 to 100. ~
+-~ ~
+-~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+-
+-Postfixes:
+-_AVG - *hardware* averaged value, use it if your hardware is really able to
+-report averaged values.
+-_NOW - momentary/instantaneous values.
+-
+-STATUS - this attribute represents operating status (charging, full,
+-discharging (i.e. powering a load), etc.). This corresponds to
+-BATTERY_STATUS_* values, as defined in battery.h.
+-
+-HEALTH - represents health of the battery, values corresponds to
+-POWER_SUPPLY_HEALTH_*, defined in battery.h.
+-
+-VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+-minimal power supply voltages. Maximal/minimal means values of voltages
+-when battery considered "full"/"empty" at normal conditions. Yes, there is
+-no direct relation between voltage and battery capacity, but some dumb
+-batteries use voltage for very approximated calculation of capacity.
+-Battery driver also can use this attribute just to inform userspace
+-about maximal and minimal voltage thresholds of a given battery.
+-
+-VOLTAGE_MAX, VOLTAGE_MIN - same as _DESIGN voltage values except that
+-these ones should be used if hardware could only guess (measure and
+-retain) the thresholds of a given power supply.
+-
+-CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+-battery considered full/empty.
+-
+-ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+-
+-CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+-of charge when battery became full/empty". It also could mean "value of
+-charge when battery considered full/empty at given conditions (temperature,
+-age)". I.e. these attributes represents real thresholds, not design values.
+-
+-ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+-
+-CAPACITY - capacity in percents.
+-
+-TEMP - temperature of the power supply.
+-TEMP_AMBIENT - ambient temperature.
+-
+-TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+-while battery powers a load)
+-TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+-while battery is charging)
+-
+-
+-Battery <-> external power supply interaction
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Often power supplies are acting as supplies and supplicants at the same
+-time. Batteries are good example. So, batteries usually care if they're
+-externally powered or not.
+-
+-For that case, power supply class implements notification mechanism for
+-batteries.
+-
+-External power supply (AC) lists supplicants (batteries) names in
+-"supplied_to" struct member, and each power_supply_changed() call
+-issued by external power supply will notify supplicants via
+-external_power_changed callback.
+-
+-
+-QA
+-~~
+-Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
+-A: If you cannot find attribute suitable for your driver needs, feel free
+- to add it and send patch along with your driver.
+-
+- The attributes available currently are the ones currently provided by the
+- drivers written.
+-
+- Good candidates to add in future: model/part#, cycle_time, manufacturer,
+- etc.
+-
+-
+-Q: I have some very specific attribute (e.g. battery color), should I add
+- this attribute to standard ones?
+-A: Most likely, no. Such attribute can be placed in the driver itself, if
+- it is useful. Of course, if the attribute in question applicable to
+- large set of batteries, provided by many drivers, and/or comes from
+- some general battery specification/standard, it may be a candidate to
+- be added to the core attribute set.
+-
+-
+-Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+- in percents, but provides charge_{now,full,empty}. Should I calculate
+- percentage capacity manually, inside the driver, and register CAPACITY
+- attribute? The same question about time_to_empty/time_to_full.
+-A: Most likely, no. This class is designed to export properties which are
+- directly measurable by the specific hardware available.
+-
+- Inferring not available properties using some heuristics or mathematical
+- model is not subject of work for a battery driver. Such functionality
+- should be factored out, and in fact, apm_power, the driver to serve
+- legacy APM API on top of power supply class, uses a simple heuristic of
+- approximating remaining battery capacity based on its charge, current,
+- voltage and so on. But full-fledged battery model is likely not subject
+- for kernel at all, as it would require floating point calculation to deal
+- with things like differential equations and Kalman filters. This is
+- better be handled by batteryd/libbattery, yet to be written.
diff --git a/Documentation/scheduler/sched-stats.txt b/Documentation/scheduler/sched-stats.txt
index 442e14d..01e6940 100644
--- a/Documentation/scheduler/sched-stats.txt
@@ -52,6 +3081,65 @@
the same information on a per-process level. There are three fields in
this file correlating for that process to:
1) time spent on the cpu
+diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
+index ba9c2da..d9f28be 100644
+--- a/Documentation/thermal/sysfs-api.txt
++++ b/Documentation/thermal/sysfs-api.txt
+@@ -143,10 +143,10 @@ type Strings which represent the thermal zone type.
+ This is given by thermal zone driver as part of registration.
+ Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
+ RO
+- Optional
++ Required
+
+ temp Current temperature as reported by thermal zone (sensor)
+- Unit: degree Celsius
++ Unit: millidegree Celsius
+ RO
+ Required
+
+@@ -163,7 +163,7 @@ mode One of the predefined values in [kernel, user]
+ charge of the thermal management.
+
+ trip_point_[0-*]_temp The temperature above which trip point will be fired
+- Unit: degree Celsius
++ Unit: millidegree Celsius
+ RO
+ Optional
+
+@@ -193,7 +193,7 @@ type String which represents the type of device
+ eg. For memory controller device on intel_menlow platform:
+ this should be "Memory controller"
+ RO
+- Optional
++ Required
+
+ max_state The maximum permissible cooling state of this cooling device.
+ RO
+@@ -219,16 +219,16 @@ the sys I/F structure will be built like this:
+
+ |thermal_zone1:
+ |-----type: ACPI thermal zone
+- |-----temp: 37
++ |-----temp: 37000
+ |-----mode: kernel
+- |-----trip_point_0_temp: 100
++ |-----trip_point_0_temp: 100000
+ |-----trip_point_0_type: critical
+- |-----trip_point_1_temp: 80
++ |-----trip_point_1_temp: 80000
+ |-----trip_point_1_type: passive
+- |-----trip_point_2_temp: 70
+- |-----trip_point_2_type: active[0]
+- |-----trip_point_3_temp: 60
+- |-----trip_point_3_type: active[1]
++ |-----trip_point_2_temp: 70000
++ |-----trip_point_2_type: active0
++ |-----trip_point_3_temp: 60000
++ |-----trip_point_3_type: active1
+ |-----cdev0: --->/sys/class/thermal/cooling_device0
+ |-----cdev0_trip_point: 1 /* cdev0 can be used for passive */
+ |-----cdev1: --->/sys/class/thermal/cooling_device3
diff --git a/Documentation/usb/usb-help.txt b/Documentation/usb/usb-help.txt
index a740859..4273ca2 100644
--- a/Documentation/usb/usb-help.txt
@@ -136,6 +3224,64 @@
M: infinipath at qlogic.com
L: general at lists.openfabrics.org
T: git git://git.qlogic.com/ipath-linux-2.6
+diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
+index 002703b..729cdbd 100644
+--- a/arch/alpha/Kconfig
++++ b/arch/alpha/Kconfig
+@@ -330,6 +330,9 @@ config PCI_DOMAINS
+ config PCI_SYSCALL
+ def_bool PCI
+
++config IOMMU_HELPER
++ def_bool PCI
++
+ config ALPHA_CORE_AGP
+ bool
+ depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
+diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
+index e07a23f..4e1c086 100644
+--- a/arch/alpha/kernel/pci_iommu.c
++++ b/arch/alpha/kernel/pci_iommu.c
+@@ -10,6 +10,7 @@
+ #include <linux/scatterlist.h>
+ #include <linux/log2.h>
+ #include <linux/dma-mapping.h>
++#include <linux/iommu-helper.h>
+
+ #include <asm/io.h>
+ #include <asm/hwrpb.h>
+@@ -125,14 +126,6 @@ iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
+ return iommu_arena_new_node(0, hose, base, window_size, align);
+ }
+
+-static inline int is_span_boundary(unsigned int index, unsigned int nr,
+- unsigned long shift,
+- unsigned long boundary_size)
+-{
+- shift = (shift + index) & (boundary_size - 1);
+- return shift + nr > boundary_size;
+-}
+-
+ /* Must be called with the arena lock held */
+ static long
+ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
+@@ -147,7 +140,6 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
+ base = arena->dma_base >> PAGE_SHIFT;
+ if (dev) {
+ boundary_size = dma_get_seg_boundary(dev) + 1;
+- BUG_ON(!is_power_of_2(boundary_size));
+ boundary_size >>= PAGE_SHIFT;
+ } else {
+ boundary_size = 1UL << (32 - PAGE_SHIFT);
+@@ -161,7 +153,7 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
+
+ again:
+ while (i < n && p+i < nent) {
+- if (!i && is_span_boundary(p, n, base, boundary_size)) {
++ if (!i && iommu_is_span_boundary(p, n, base, boundary_size)) {
+ p = ALIGN(p + 1, mask + 1);
+ goto again;
+ }
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 7b8ff66..1a46496 100644
--- a/arch/arm/Makefile
@@ -8480,7 +11626,7 @@
stw r10, 0(r11) /* and update pte in table */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index f41c953..237fc12 100644
+index f41c953..6c70fed 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -66,9 +66,6 @@ config MMU
@@ -8493,6 +11639,15 @@
config SBUS
bool
+@@ -1262,7 +1259,7 @@ menuconfig APM
+ machines with more than one CPU.
+
+ In order to use APM, you will need supporting software. For location
+- and more information, read <file:Documentation/pm.txt> and the
++ and more information, read <file:Documentation/power/pm.txt> and the
+ Battery Powered Linux mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 8f64abe..d5904ee 100644
--- a/arch/x86/kernel/ptrace.c
@@ -8802,29 +11957,714 @@
bdev_map = kobj_map_init(base_probe, &block_class_lock);
blk_dev_init();
-diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
-index ba8f7f4..e469647 100644
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -538,6 +538,15 @@ config PATA_RADISYS
+diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
+index 0f62822..84caa4e 100644
+--- a/crypto/async_tx/async_memcpy.c
++++ b/crypto/async_tx/async_memcpy.c
+@@ -66,11 +66,11 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ }
- If unsure, say N.
+ if (tx) {
+- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (async) len: %zu\n", __func__, len);
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else {
+ void *dest_buf, *src_buf;
+- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (sync) len: %zu\n", __func__, len);
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+@@ -80,7 +80,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+- __FUNCTION__);
++ __func__);
+ }
-+config PATA_RB500
-+ tristate "RouterBoard 500 PATA CompactFlash support"
-+ depends on MIKROTIK_RB500
-+ help
-+ This option enables support for the RouterBoard 500
-+ PATA CompactFlash controller.
-+
-+ If unsure, say N.
-+
- config PATA_RZ1000
- tristate "PC Tech RZ1000 PATA support"
- depends on PCI
-diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
-index 701651e..0511e6f 100644
---- a/drivers/ata/Makefile
+ dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
+index 09c0e83..f5ff390 100644
+--- a/crypto/async_tx/async_memset.c
++++ b/crypto/async_tx/async_memset.c
+@@ -63,11 +63,11 @@ async_memset(struct page *dest, int val, unsigned int offset,
+ }
+
+ if (tx) {
+- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (async) len: %zu\n", __func__, len);
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else { /* run the memset synchronously */
+ void *dest_buf;
+- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (sync) len: %zu\n", __func__, len);
+
+ dest_buf = (void *) (((char *) page_address(dest)) + offset);
+
+@@ -79,7 +79,7 @@ async_memset(struct page *dest, int val, unsigned int offset,
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+- __FUNCTION__);
++ __func__);
+ }
+
+ memset(dest_buf, val, len);
+diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
+index 5628821..2be3bae 100644
+--- a/crypto/async_tx/async_tx.c
++++ b/crypto/async_tx/async_tx.c
+@@ -472,11 +472,11 @@ async_trigger_callback(enum async_tx_flags flags,
+ tx = NULL;
+
+ if (tx) {
+- pr_debug("%s: (async)\n", __FUNCTION__);
++ pr_debug("%s: (async)\n", __func__);
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else {
+- pr_debug("%s: (sync)\n", __FUNCTION__);
++ pr_debug("%s: (sync)\n", __func__);
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+@@ -486,7 +486,7 @@ async_trigger_callback(enum async_tx_flags flags,
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+- __FUNCTION__);
++ __func__);
+ }
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
+index 2259a4f..7a9db35 100644
+--- a/crypto/async_tx/async_xor.c
++++ b/crypto/async_tx/async_xor.c
+@@ -47,7 +47,7 @@ do_async_xor(struct dma_device *device,
+ int i;
+ unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
+
+- pr_debug("%s: len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: len: %zu\n", __func__, len);
+
+ dma_dest = dma_map_page(device->dev, dest, offset, len,
+ DMA_FROM_DEVICE);
+@@ -86,7 +86,7 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ void *_dest;
+ int i;
+
+- pr_debug("%s: len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: len: %zu\n", __func__, len);
+
+ /* reuse the 'src_list' array to convert to buffer pointers */
+ for (i = 0; i < src_cnt; i++)
+@@ -196,7 +196,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for "
+ "depend_tx\n",
+- __FUNCTION__);
++ __func__);
+ }
+
+ do_sync_xor(dest, &src_list[src_off], offset,
+@@ -276,7 +276,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
+ unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
+ int i;
+
+- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (async) len: %zu\n", __func__, len);
+
+ for (i = 0; i < src_cnt; i++)
+ dma_src[i] = dma_map_page(device->dev, src_list[i],
+@@ -299,7 +299,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
+ } else {
+ unsigned long xor_flags = flags;
+
+- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
++ pr_debug("%s: (sync) len: %zu\n", __func__, len);
+
+ xor_flags |= ASYNC_TX_XOR_DROP_DST;
+ xor_flags &= ~ASYNC_TX_ACK;
+@@ -310,7 +310,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
+ if (tx) {
+ if (dma_wait_for_async_tx(tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for tx\n",
+- __FUNCTION__);
++ __func__);
+ async_tx_ack(tx);
+ }
+
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index f688c21..fbcaa06 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -283,24 +283,23 @@ config ACPI_TOSHIBA
+ If you have a legacy free Toshiba laptop (such as the Libretto L1
+ series), say Y.
+
+-config ACPI_CUSTOM_DSDT
+- bool "Include Custom DSDT"
++config ACPI_CUSTOM_DSDT_FILE
++ string "Custom DSDT Table file to include"
++ default ""
+ depends on !STANDALONE
+- default n
+ help
+ This option supports a custom DSDT by linking it into the kernel.
+ See Documentation/acpi/dsdt-override.txt
+
+- If unsure, say N.
+-
+-config ACPI_CUSTOM_DSDT_FILE
+- string "Custom DSDT Table file to include"
+- depends on ACPI_CUSTOM_DSDT
+- default ""
+- help
+ Enter the full path name to the file which includes the AmlCode
+ declaration.
+
++ If unsure, don't enter a file name.
++
++config ACPI_CUSTOM_DSDT
++ bool
++ default ACPI_CUSTOM_DSDT_FILE != ""
++
+ config ACPI_CUSTOM_DSDT_INITRD
+ bool "Read Custom DSDT from initramfs"
+ depends on BLK_DEV_INITRD
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index ce3c0a2..5b6760e 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -776,7 +776,7 @@ static int __init acpi_init(void)
+
+ acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
+ if (!acpi_kobj) {
+- printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: kset create error\n", __func__);
+ acpi_kobj = NULL;
+ }
+
+diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
+index 24a7865..6c5da83 100644
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -449,6 +449,7 @@ static int acpi_button_add(struct acpi_device *device)
+ input->phys = button->phys;
+ input->id.bustype = BUS_HOST;
+ input->id.product = button->type;
++ input->dev.parent = &device->dev;
+
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWER:
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index caf873c..e7e197e 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -129,6 +129,7 @@ static struct acpi_ec {
+ struct mutex lock;
+ wait_queue_head_t wait;
+ struct list_head list;
++ atomic_t irq_count;
+ u8 handlers_installed;
+ } *boot_ec, *first_ec;
+
+@@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+ {
+ int ret = 0;
+
++ atomic_set(&ec->irq_count, 0);
++
+ if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
+ test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
+ force_poll = 1;
+@@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+ while (time_before(jiffies, delay)) {
+ if (acpi_ec_check_status(ec, event))
+ goto end;
++ msleep(5);
+ }
+ }
+ pr_err(PREFIX "acpi_ec_wait timeout,"
+@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data)
+ struct acpi_ec *ec = data;
+
+ pr_debug(PREFIX "~~~> interrupt\n");
++ atomic_inc(&ec->irq_count);
++ if (atomic_read(&ec->irq_count) > 5) {
++ pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
++ acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR);
++ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
++ return ACPI_INTERRUPT_HANDLED;
++ }
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
+ wake_up(&ec->wait);
+@@ -943,11 +954,7 @@ int __init acpi_ec_ecdt_probe(void)
+ boot_ec->command_addr = ecdt_ptr->control.address;
+ boot_ec->data_addr = ecdt_ptr->data.address;
+ boot_ec->gpe = ecdt_ptr->gpe;
+- if (ACPI_FAILURE(acpi_get_handle(NULL, ecdt_ptr->id,
+- &boot_ec->handle))) {
+- pr_info("Failed to locate handle for boot EC\n");
+- boot_ec->handle = ACPI_ROOT_OBJECT;
+- }
++ boot_ec->handle = ACPI_ROOT_OBJECT;
+ } else {
+ /* This workaround is needed only on some broken machines,
+ * which require early EC, but fail to provide ECDT */
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index 8edba7b..065819b 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -1237,7 +1237,7 @@ int acpi_check_resource_conflict(struct resource *res)
+
+ if (clash) {
+ if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
+- printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
++ printk("%sACPI: %s resource %s [0x%llx-0x%llx]"
+ " conflicts with ACPI region %s"
+ " [0x%llx-0x%llx]\n",
+ acpi_enforce_resources == ENFORCE_RESOURCES_LAX
+diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
+index 7f19859..7af414a 100644
+--- a/drivers/acpi/pci_irq.c
++++ b/drivers/acpi/pci_irq.c
+@@ -25,6 +25,7 @@
+ */
+
+
++#include <linux/dmi.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
+ return NULL;
+ }
+
++/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
++static struct dmi_system_id medion_md9580[] = {
++ {
++ .ident = "Medion MD9580-F laptop",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "A555"),
++ },
++ },
++ { }
++};
++
++/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */
++static struct dmi_system_id dell_optiplex[] = {
++ {
++ .ident = "Dell Optiplex GX1",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"),
++ },
++ },
++ { }
++};
++
++/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */
++static struct dmi_system_id hp_t5710[] = {
++ {
++ .ident = "HP t5710",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"),
++ DMI_MATCH(DMI_BOARD_NAME, "098Ch"),
++ },
++ },
++ { }
++};
++
++struct prt_quirk {
++ struct dmi_system_id *system;
++ unsigned int segment;
++ unsigned int bus;
++ unsigned int device;
++ unsigned char pin;
++ char *source; /* according to BIOS */
++ char *actual_source;
++};
++
++/*
++ * These systems have incorrect _PRT entries. The BIOS claims the PCI
++ * interrupt at the listed segment/bus/device/pin is connected to the first
++ * link device, but it is actually connected to the second.
++ */
++static struct prt_quirk prt_quirks[] = {
++ { medion_md9580, 0, 0, 9, 'A',
++ "\\_SB_.PCI0.ISA.LNKA",
++ "\\_SB_.PCI0.ISA.LNKB"},
++ { dell_optiplex, 0, 0, 0xd, 'A',
++ "\\_SB_.LNKB",
++ "\\_SB_.LNKA"},
++ { hp_t5710, 0, 0, 1, 'A',
++ "\\_SB_.PCI0.LNK1",
++ "\\_SB_.PCI0.LNK3"},
++};
++
++static void
++do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
++{
++ int i;
++ struct prt_quirk *quirk;
++
++ for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) {
++ quirk = &prt_quirks[i];
++
++ /* All current quirks involve link devices, not GSIs */
++ if (!prt->source)
++ continue;
++
++ if (dmi_check_system(quirk->system) &&
++ entry->id.segment == quirk->segment &&
++ entry->id.bus == quirk->bus &&
++ entry->id.device == quirk->device &&
++ entry->pin + 'A' == quirk->pin &&
++ !strcmp(prt->source, quirk->source) &&
++ strlen(prt->source) >= strlen(quirk->actual_source)) {
++ printk(KERN_WARNING PREFIX "firmware reports "
++ "%04x:%02x:%02x[%c] connected to %s; "
++ "changing to %s\n",
++ entry->id.segment, entry->id.bus,
++ entry->id.device, 'A' + entry->pin,
++ prt->source, quirk->actual_source);
++ strcpy(prt->source, quirk->actual_source);
++ }
++ }
++}
++
+ static int
+ acpi_pci_irq_add_entry(acpi_handle handle,
+ int segment, int bus, struct acpi_pci_routing_table *prt)
+@@ -96,6 +192,8 @@ acpi_pci_irq_add_entry(acpi_handle handle,
+ entry->id.function = prt->address & 0xFFFF;
+ entry->pin = prt->pin;
+
++ do_prt_fixups(entry, prt);
++
+ /*
+ * Type 1: Dynamic
+ * ---------------
+diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
+index f14ff1f..c3fed31 100644
+--- a/drivers/acpi/pci_root.c
++++ b/drivers/acpi/pci_root.c
+@@ -184,7 +184,7 @@ static void acpi_pci_bridge_scan(struct acpi_device *device)
+ }
+ }
+
+-static int acpi_pci_root_add(struct acpi_device *device)
++static int __devinit acpi_pci_root_add(struct acpi_device *device)
+ {
+ int result = 0;
+ struct acpi_pci_root *root = NULL;
+diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
+index a3cc8a9..36a68fa 100644
+--- a/drivers/acpi/processor_core.c
++++ b/drivers/acpi/processor_core.c
+@@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle)
+
+
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+- /*
+- * if a processor object does not have an _STA object,
+- * OSPM assumes that the processor is present.
+- */
+- if (status == AE_NOT_FOUND)
+- return 1;
+
+ if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
+ return 1;
+
+- ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
++ /*
++ * _STA is mandatory for a processor that supports hot plug
++ */
++ if (status == AE_NOT_FOUND)
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Processor does not support hot plug\n"));
++ else
++ ACPI_EXCEPTION((AE_INFO, status,
++ "Processor Device is not present"));
+ return 0;
+ }
+
+@@ -886,8 +888,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
+ return 0;
+ }
+
+-static void
+-acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
++static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
++ u32 event, void *data)
+ {
+ struct acpi_processor *pr;
+ struct acpi_device *device = NULL;
+@@ -897,9 +899,10 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
+ switch (event) {
+ case ACPI_NOTIFY_BUS_CHECK:
+ case ACPI_NOTIFY_DEVICE_CHECK:
+- printk("Processor driver received %s event\n",
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Processor driver received %s event\n",
+ (event == ACPI_NOTIFY_BUS_CHECK) ?
+- "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
++ "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
+
+ if (!is_processor_present(handle))
+ break;
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 3fac011..57570ac 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -609,7 +609,8 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
+ status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ obj = buffer.pointer;
+- status = acpi_get_handle(NULL, obj->string.pointer, ejd);
++ status = acpi_get_handle(ACPI_ROOT_OBJECT, obj->string.pointer,
++ ejd);
+ kfree(buffer.pointer);
+ }
+ return status;
+@@ -966,7 +967,7 @@ static void acpi_device_set_id(struct acpi_device *device,
+ case ACPI_BUS_TYPE_DEVICE:
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_FAILURE(status)) {
+- printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__);
++ printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
+ return;
+ }
+
+diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
+index 293a1cb..d2f71a5 100644
+--- a/drivers/acpi/sleep/main.c
++++ b/drivers/acpi/sleep/main.c
+@@ -504,7 +504,7 @@ static void acpi_power_off_prepare(void)
+ static void acpi_power_off(void)
+ {
+ /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
+- printk("%s called\n", __FUNCTION__);
++ printk("%s called\n", __func__);
+ local_irq_disable();
+ acpi_enable_wakeup_device(ACPI_STATE_S5);
+ acpi_enter_sleep_state(ACPI_STATE_S5);
+diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
+index 55cf4c0..4749f37 100644
+--- a/drivers/acpi/system.c
++++ b/drivers/acpi/system.c
+@@ -319,7 +319,7 @@ void acpi_irq_stats_init(void)
+ goto fail;
+
+ for (i = 0; i < num_counters; ++i) {
+- char buffer[10];
++ char buffer[12];
+ char *name;
+
+ if (i < num_gpes)
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index 8d4b79b..c4e00ac 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -879,6 +879,8 @@ static void acpi_thermal_check(void *data)
+ }
+
+ /* sys I/F for generic thermal sysfs support */
++#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
++
+ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
+ {
+ struct acpi_thermal *tz = thermal->devdata;
+@@ -886,7 +888,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
+ if (!tz)
+ return -EINVAL;
+
+- return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
++ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
+ }
+
+ static const char enabled[] = "kernel";
+@@ -980,21 +982,21 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+
+ if (tz->trips.critical.flags.valid) {
+ if (!trip)
+- return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+ tz->trips.critical.temperature));
+ trip--;
+ }
+
+ if (tz->trips.hot.flags.valid) {
+ if (!trip)
+- return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+ tz->trips.hot.temperature));
+ trip--;
+ }
+
+ if (tz->trips.passive.flags.valid) {
+ if (!trip)
+- return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+ tz->trips.passive.temperature));
+ trip--;
+ }
+@@ -1002,7 +1004,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
+ tz->trips.active[i].flags.valid; i++) {
+ if (!trip)
+- return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++ return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+ tz->trips.active[i].temperature));
+ trip--;
+ }
+diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
+index 9e8c20c..0a43c8e 100644
+--- a/drivers/acpi/toshiba_acpi.c
++++ b/drivers/acpi/toshiba_acpi.c
+@@ -99,6 +99,13 @@ MODULE_LICENSE("GPL");
+ #define HCI_VIDEO_OUT_CRT 0x2
+ #define HCI_VIDEO_OUT_TV 0x4
+
++static const struct acpi_device_id toshiba_device_ids[] = {
++ {"TOS6200", 0},
++ {"TOS1900", 0},
++ {"", 0},
++};
++MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
++
+ /* utility
+ */
+
+diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
+index c7e128e..7361204 100644
+--- a/drivers/acpi/utilities/utdebug.c
++++ b/drivers/acpi/utilities/utdebug.c
+@@ -109,7 +109,7 @@ void acpi_ut_track_stack_ptr(void)
+ * RETURN: Updated pointer to the function name
+ *
+ * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
+- * This allows compiler macros such as __FUNCTION__ to be used
++ * This allows compiler macros such as __func__ to be used
+ * with no change to the debug output.
+ *
+ ******************************************************************************/
+diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
+index 76ee766..e08b3fa 100644
+--- a/drivers/acpi/utilities/utobject.c
++++ b/drivers/acpi/utilities/utobject.c
+@@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
+ * element -- which is legal)
+ */
+ if (!internal_object) {
+- *obj_length = 0;
++ *obj_length = sizeof(union acpi_object);
+ return_ACPI_STATUS(AE_OK);
+ }
+
+diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
+index eba55b7..44ea60c 100644
+--- a/drivers/acpi/utils.c
++++ b/drivers/acpi/utils.c
+@@ -407,6 +407,12 @@ acpi_evaluate_reference(acpi_handle handle,
+ break;
+ }
+
++ if (!element->reference.handle) {
++ printk(KERN_WARNING PREFIX "Invalid reference in"
++ " package %s\n", pathname);
++ status = AE_NULL_ENTRY;
++ break;
++ }
+ /* Get the acpi_handle. */
+
+ list->handles[i] = element->reference.handle;
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index 12cce69..1bc0c74 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
+
+ kfree(obj);
+
+- if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
++ if (device->cap._BCL && device->cap._BCM && max_level > 0) {
+ int result;
+ static int count = 0;
+ char *name;
+@@ -1201,7 +1201,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
+ if (!video)
+ goto end;
+
+- printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
++ printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
+ seq_printf(seq, "<TODO>\n");
+
+ end:
+diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
+index efacc9f..c33b1c6 100644
+--- a/drivers/acpi/wmi.c
++++ b/drivers/acpi/wmi.c
+@@ -293,7 +293,7 @@ struct acpi_buffer *out)
+ {
+ struct guid_block *block = NULL;
+ struct wmi_block *wblock = NULL;
+- acpi_handle handle;
++ acpi_handle handle, wc_handle;
+ acpi_status status, wc_status = AE_ERROR;
+ struct acpi_object_list input, wc_input;
+ union acpi_object wc_params[1], wq_params[1];
+@@ -338,8 +338,10 @@ struct acpi_buffer *out)
+ * expensive, but have no corresponding WCxx method. So we
+ * should not fail if this happens.
+ */
+- wc_status = acpi_evaluate_object(handle, wc_method,
+- &wc_input, NULL);
++ wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
++ if (ACPI_SUCCESS(wc_status))
++ wc_status = acpi_evaluate_object(handle, wc_method,
++ &wc_input, NULL);
+ }
+
+ strcpy(method, "WQ");
+@@ -351,7 +353,7 @@ struct acpi_buffer *out)
+ * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
+ * the WQxx method failed - we should disable collection anyway.
+ */
+- if ((block->flags & ACPI_WMI_EXPENSIVE) && wc_status) {
++ if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
+ wc_params[0].integer.value = 0;
+ status = acpi_evaluate_object(handle,
+ wc_method, &wc_input, NULL);
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index ba8f7f4..e469647 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -538,6 +538,15 @@ config PATA_RADISYS
+
+ If unsure, say N.
+
++config PATA_RB500
++ tristate "RouterBoard 500 PATA CompactFlash support"
++ depends on MIKROTIK_RB500
++ help
++ This option enables support for the RouterBoard 500
++ PATA CompactFlash controller.
++
++ If unsure, say N.
++
+ config PATA_RZ1000
+ tristate "PC Tech RZ1000 PATA support"
+ depends on PCI
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index 701651e..0511e6f 100644
+--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
@@ -9543,6 +13383,43 @@
/* Make sure the kset is set */
sysdev->kobj.kset = &cls->kset;
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 32c79a5..7652e87 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -217,7 +217,6 @@ static int use_virtual_dma;
+ */
+
+ static DEFINE_SPINLOCK(floppy_lock);
+-static struct completion device_release;
+
+ static unsigned short virtual_dma_port = 0x3f0;
+ irqreturn_t floppy_interrupt(int irq, void *dev_id);
+@@ -4144,7 +4143,6 @@ DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
+ static void floppy_device_release(struct device *dev)
+ {
+- complete(&device_release);
+ }
+
+ static struct platform_device floppy_device[N_DRIVE];
+@@ -4539,7 +4537,6 @@ void cleanup_module(void)
+ {
+ int drive;
+
+- init_completion(&device_release);
+ blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
+ unregister_blkdev(FLOPPY_MAJOR, "fd");
+
+@@ -4564,8 +4561,6 @@ void cleanup_module(void)
+
+ /* eject disk, if any */
+ fd_eject(0);
+-
+- wait_for_completion(&device_release);
+ }
+
+ module_param(floppy, charp, 0);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 9e61fca..41ca721 100644
--- a/drivers/block/viodasd.c
@@ -9727,7 +13604,7 @@
static int ntty_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
-index 8fc4fe4..589ac6f 100644
+index 8fc4fe4..3f9d0a9 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1620,14 +1620,8 @@ static int __init rc_init_drivers(void)
@@ -9745,6 +13622,334 @@
}
#ifndef MODULE
+@@ -1715,7 +1709,7 @@ static int __init riscom8_init_module (void)
+
+ if (iobase || iobase1 || iobase2 || iobase3) {
+ for(i = 0; i < RC_NBOARD; i++)
+- rc_board[0].base = 0;
++ rc_board[i].base = 0;
+ }
+
+ if (iobase)
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index 2996523..8db0e7f 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -357,7 +357,7 @@ int dma_async_device_register(struct dma_device *device)
+ !device->device_prep_dma_zero_sum);
+ BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
+ !device->device_prep_dma_memset);
+- BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
++ BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
+ !device->device_prep_dma_interrupt);
+
+ BUG_ON(!device->device_alloc_chan_resources);
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index cc9a681..ad2f938 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -57,12 +57,12 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
+
+ }
+
+-static void set_sr(struct fsl_dma_chan *fsl_chan, dma_addr_t val)
++static void set_sr(struct fsl_dma_chan *fsl_chan, u32 val)
+ {
+ DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
+ }
+
+-static dma_addr_t get_sr(struct fsl_dma_chan *fsl_chan)
++static u32 get_sr(struct fsl_dma_chan *fsl_chan)
+ {
+ return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
+ }
+@@ -406,6 +406,32 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ dma_pool_destroy(fsl_chan->desc_pool);
+ }
+
++static struct dma_async_tx_descriptor *
++fsl_dma_prep_interrupt(struct dma_chan *chan)
++{
++ struct fsl_dma_chan *fsl_chan;
++ struct fsl_desc_sw *new;
++
++ if (!chan)
++ return NULL;
++
++ fsl_chan = to_fsl_chan(chan);
++
++ new = fsl_dma_alloc_descriptor(fsl_chan);
++ if (!new) {
++ dev_err(fsl_chan->dev, "No free memory for link descriptor\n");
++ return NULL;
++ }
++
++ new->async_tx.cookie = -EBUSY;
++ new->async_tx.ack = 0;
++
++ /* Set End-of-link to the last link descriptor of new list*/
++ set_ld_eol(fsl_chan, new);
++
++ return &new->async_tx;
++}
++
+ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+ size_t len, unsigned long flags)
+@@ -436,7 +462,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+ #endif
+
+- copy = min(len, FSL_DMA_BCR_MAX_CNT);
++ copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
+
+ set_desc_cnt(fsl_chan, &new->hw, copy);
+ set_desc_src(fsl_chan, &new->hw, dma_src);
+@@ -513,7 +539,6 @@ static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
+
+ spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+
+- fsl_dma_update_completed_cookie(fsl_chan);
+ dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n",
+ fsl_chan->completed_cookie);
+ list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+@@ -581,8 +606,8 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+ if (ld_node != &fsl_chan->ld_queue) {
+ /* Get the ld start address from ld_queue */
+ next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
+- dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%016llx\n",
+- (u64)next_dest_addr);
++ dev_dbg(fsl_chan->dev, "xfer LDs staring from %p\n",
++ (void *)next_dest_addr);
+ set_cdar(fsl_chan, next_dest_addr);
+ dma_start(fsl_chan);
+ } else {
+@@ -662,7 +687,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ {
+ struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+- dma_addr_t stat;
++ u32 stat;
+
+ stat = get_sr(fsl_chan);
+ dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
+@@ -681,10 +706,10 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ */
+ if (stat & FSL_DMA_SR_EOSI) {
+ dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n");
+- dev_dbg(fsl_chan->dev, "event: clndar 0x%016llx, "
+- "nlndar 0x%016llx\n", (u64)get_cdar(fsl_chan),
+- (u64)get_ndar(fsl_chan));
++ dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
++ (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
+ stat &= ~FSL_DMA_SR_EOSI;
++ fsl_dma_update_completed_cookie(fsl_chan);
+ }
+
+ /* If it current transfer is the end-of-transfer,
+@@ -726,12 +751,15 @@ static void dma_do_tasklet(unsigned long data)
+ fsl_chan_ld_cleanup(fsl_chan);
+ }
+
++#ifdef FSL_DMA_CALLBACKTEST
+ static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
+ {
+ if (fsl_chan)
+ dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
+ }
++#endif
+
++#ifdef CONFIG_FSL_DMA_SELFTEST
+ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ {
+ struct dma_chan *chan;
+@@ -837,9 +865,9 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ if (err) {
+ for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size);
+ i++);
+- dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%d is "
++ dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%ld is "
+ "error! src 0x%x, dest 0x%x\n",
+- i, test_size, *(src + i), *(dest + i));
++ i, (long)test_size, *(src + i), *(dest + i));
+ }
+
+ free_resources:
+@@ -848,6 +876,7 @@ out:
+ kfree(src);
+ return err;
+ }
++#endif
+
+ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ const struct of_device_id *match)
+@@ -1008,8 +1037,8 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ }
+
+ dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
+- "controller at 0x%08x...\n",
+- match->compatible, fdev->reg.start);
++ "controller at %p...\n",
++ match->compatible, (void *)fdev->reg.start);
+ fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
+ - fdev->reg.start + 1);
+
+@@ -1017,6 +1046,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
+ fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
+ fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
++ fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
+ fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+ fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+ fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index 3986d54..f82b090 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -140,7 +140,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ int busy = iop_chan_is_busy(iop_chan);
+ int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+
+- dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
+ /* free completed slots from the chain starting with
+ * the oldest descriptor
+ */
+@@ -438,7 +438,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+ spin_unlock_bh(&iop_chan->lock);
+
+ dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
+- __FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
++ __func__, sw_desc->async_tx.cookie, sw_desc->idx);
+
+ return cookie;
+ }
+@@ -520,7 +520,7 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+- dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
+@@ -548,7 +548,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
+ BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+ dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+- __FUNCTION__, len);
++ __func__, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
+@@ -580,7 +580,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,
+ BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+ dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+- __FUNCTION__, len);
++ __func__, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
+@@ -614,7 +614,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
+
+ dev_dbg(iop_chan->device->common.dev,
+ "%s src_cnt: %d len: %u flags: %lx\n",
+- __FUNCTION__, src_cnt, len, flags);
++ __func__, src_cnt, len, flags);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+@@ -648,7 +648,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ return NULL;
+
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+- __FUNCTION__, src_cnt, len);
++ __func__, src_cnt, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
+@@ -659,7 +659,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ iop_desc_set_zero_sum_byte_count(grp_start, len);
+ grp_start->xor_check_result = result;
+ pr_debug("\t%s: grp_start->xor_check_result: %p\n",
+- __FUNCTION__, grp_start->xor_check_result);
++ __func__, grp_start->xor_check_result);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
+ while (src_cnt--)
+@@ -700,7 +700,7 @@ static void iop_adma_free_chan_resources(struct dma_chan *chan)
+ iop_chan->last_used = NULL;
+
+ dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
+- __FUNCTION__, iop_chan->slots_allocated);
++ __func__, iop_chan->slots_allocated);
+ spin_unlock_bh(&iop_chan->lock);
+
+ /* one is ok since we left it on there on purpose */
+@@ -753,7 +753,7 @@ static irqreturn_t iop_adma_eot_handler(int irq, void *data)
+ {
+ struct iop_adma_chan *chan = data;
+
+- dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(chan->device->common.dev, "%s\n", __func__);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+@@ -766,7 +766,7 @@ static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
+ {
+ struct iop_adma_chan *chan = data;
+
+- dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(chan->device->common.dev, "%s\n", __func__);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+@@ -823,7 +823,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ int err = 0;
+ struct iop_adma_chan *iop_chan;
+
+- dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(device->common.dev, "%s\n", __func__);
+
+ src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+ if (!src)
+@@ -906,7 +906,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ int err = 0;
+ struct iop_adma_chan *iop_chan;
+
+- dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(device->common.dev, "%s\n", __func__);
+
+ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+ xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+@@ -1159,7 +1159,7 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ }
+
+ dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
+- __FUNCTION__, adev->dma_desc_pool_virt,
++ __func__, adev->dma_desc_pool_virt,
+ (void *) adev->dma_desc_pool);
+
+ adev->id = plat_data->hw_id;
+@@ -1289,7 +1289,7 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+ dma_cookie_t cookie;
+ int slot_cnt, slots_per_op;
+
+- dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
+@@ -1346,7 +1346,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+ dma_cookie_t cookie;
+ int slot_cnt, slots_per_op;
+
+- dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
++ dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 92583cd..6e72fd3 100644
--- a/drivers/gpio/pca953x.c
@@ -9958,6 +14163,324 @@
qhp->rhp = rhp;
qhp->attr.pd = php->pdid;
qhp->attr.scq = ((struct iwch_cq *) attrs->send_cq)->cq.cqid;
+diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
+index 4146210..591901a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_common.h
++++ b/drivers/infiniband/hw/ipath/ipath_common.h
+@@ -75,7 +75,7 @@
+ #define IPATH_IB_LINKDOWN 0
+ #define IPATH_IB_LINKARM 1
+ #define IPATH_IB_LINKACTIVE 2
+-#define IPATH_IB_LINKINIT 3
++#define IPATH_IB_LINKDOWN_ONLY 3
+ #define IPATH_IB_LINKDOWN_SLEEP 4
+ #define IPATH_IB_LINKDOWN_DISABLE 5
+ #define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
+diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
+index d5ff6ca..ca4d0ac 100644
+--- a/drivers/infiniband/hw/ipath/ipath_driver.c
++++ b/drivers/infiniband/hw/ipath/ipath_driver.c
+@@ -851,8 +851,7 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ * -ETIMEDOUT state can have multiple states set, for any of several
+ * transitions.
+ */
+-static int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state,
+- int msecs)
++int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+ {
+ dd->ipath_state_wanted = state;
+ wait_event_interruptible_timeout(ipath_state_wait,
+@@ -1656,8 +1655,8 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
+ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
+ {
+ static const char *what[4] = {
+- [0] = "DOWN",
+- [INFINIPATH_IBCC_LINKCMD_INIT] = "INIT",
++ [0] = "NOP",
++ [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN",
+ [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+ [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+ };
+@@ -1672,9 +1671,9 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
+ (dd, dd->ipath_kregs->kr_ibcstatus) >>
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+- /* flush all queued sends when going to DOWN or INIT, to be sure that
++ /* flush all queued sends when going to DOWN to be sure that
+ * they don't block MAD packets */
+- if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT)
++ if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN)
+ ipath_cancel_sends(dd, 1);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+@@ -1687,6 +1686,13 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ int ret;
+
+ switch (newstate) {
++ case IPATH_IB_LINKDOWN_ONLY:
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN <<
++ INFINIPATH_IBCC_LINKCMD_SHIFT);
++ /* don't wait */
++ ret = 0;
++ goto bail;
++
+ case IPATH_IB_LINKDOWN:
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+@@ -1709,16 +1715,6 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ ret = 0;
+ goto bail;
+
+- case IPATH_IB_LINKINIT:
+- if (dd->ipath_flags & IPATH_LINKINIT) {
+- ret = 0;
+- goto bail;
+- }
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
+- INFINIPATH_IBCC_LINKCMD_SHIFT);
+- lstate = IPATH_LINKINIT;
+- break;
+-
+ case IPATH_IB_LINKARM:
+ if (dd->ipath_flags & IPATH_LINKARMED) {
+ ret = 0;
+diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
+index 4cc0f95..ecf3f7f 100644
+--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
++++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
+@@ -767,6 +767,7 @@ void ipath_kreceive(struct ipath_portdata *);
+ int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
+ int ipath_reset_device(int);
+ void ipath_get_faststats(unsigned long);
++int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
+ int ipath_set_linkstate(struct ipath_devdata *, u8);
+ int ipath_set_mtu(struct ipath_devdata *, u16);
+ int ipath_set_lid(struct ipath_devdata *, u32, u8);
+diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
+index d98d5f1..b34b91d 100644
+--- a/drivers/infiniband/hw/ipath/ipath_mad.c
++++ b/drivers/infiniband/hw/ipath/ipath_mad.c
+@@ -555,10 +555,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ /* FALLTHROUGH */
+ case IB_PORT_DOWN:
+ if (lstate == 0)
+- if (get_linkdowndefaultstate(dd))
+- lstate = IPATH_IB_LINKDOWN_SLEEP;
+- else
+- lstate = IPATH_IB_LINKDOWN;
++ lstate = IPATH_IB_LINKDOWN_ONLY;
+ else if (lstate == 1)
+ lstate = IPATH_IB_LINKDOWN_SLEEP;
+ else if (lstate == 2)
+@@ -568,6 +565,8 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ else
+ goto err;
+ ipath_set_linkstate(dd, lstate);
++ ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
++ IPATH_LINKACTIVE, 1000);
+ break;
+ case IB_PORT_ARMED:
+ ipath_set_linkstate(dd, IPATH_IB_LINKARM);
+diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
+index 80dc623..087ed31 100644
+--- a/drivers/infiniband/hw/ipath/ipath_qp.c
++++ b/drivers/infiniband/hw/ipath/ipath_qp.c
+@@ -329,8 +329,9 @@ struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn)
+ /**
+ * ipath_reset_qp - initialize the QP state to the reset state
+ * @qp: the QP to reset
++ * @type: the QP type
+ */
+-static void ipath_reset_qp(struct ipath_qp *qp)
++static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type)
+ {
+ qp->remote_qpn = 0;
+ qp->qkey = 0;
+@@ -342,7 +343,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
+ qp->s_psn = 0;
+ qp->r_psn = 0;
+ qp->r_msn = 0;
+- if (qp->ibqp.qp_type == IB_QPT_RC) {
++ if (type == IB_QPT_RC) {
+ qp->s_state = IB_OPCODE_RC_SEND_LAST;
+ qp->r_state = IB_OPCODE_RC_SEND_LAST;
+ } else {
+@@ -414,7 +415,7 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
+ wc.wr_id = qp->r_wr_id;
+ wc.opcode = IB_WC_RECV;
+ wc.status = err;
+- ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
++ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+ }
+ wc.status = IB_WC_WR_FLUSH_ERR;
+
+@@ -534,7 +535,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+
+ switch (new_state) {
+ case IB_QPS_RESET:
+- ipath_reset_qp(qp);
++ ipath_reset_qp(qp, ibqp->qp_type);
+ break;
+
+ case IB_QPS_ERR:
+@@ -647,7 +648,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ attr->port_num = 1;
+ attr->timeout = qp->timeout;
+ attr->retry_cnt = qp->s_retry_cnt;
+- attr->rnr_retry = qp->s_rnr_retry;
++ attr->rnr_retry = qp->s_rnr_retry_cnt;
+ attr->alt_port_num = 0;
+ attr->alt_timeout = 0;
+
+@@ -839,7 +840,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ goto bail_qp;
+ }
+ qp->ip = NULL;
+- ipath_reset_qp(qp);
++ ipath_reset_qp(qp, init_attr->qp_type);
+ break;
+
+ default:
+diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
+index 459e46e..40f3e37 100644
+--- a/drivers/infiniband/hw/ipath/ipath_rc.c
++++ b/drivers/infiniband/hw/ipath/ipath_rc.c
+@@ -1196,6 +1196,10 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
+ list_move_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
++
++ if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE))
++ qp->s_retry = qp->s_retry_cnt;
++
+ /*
+ * Update the RDMA receive state but do the copy w/o
+ * holding the locks and blocking interrupts.
+diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
+index 6d2a17f..92ad73a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_registers.h
++++ b/drivers/infiniband/hw/ipath/ipath_registers.h
+@@ -185,7 +185,7 @@
+ #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
+ #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+ #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+-#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */
++#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */
+ #define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
+ #define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
+ #define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+index 52b1beb..2490b2d 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+@@ -38,6 +38,7 @@
+ #include <net/icmp.h>
+ #include <linux/icmpv6.h>
+ #include <linux/delay.h>
++#include <linux/vmalloc.h>
+
+ #include "ipoib.h"
+
+@@ -637,6 +638,7 @@ static inline int post_send(struct ipoib_dev_priv *priv,
+ priv->tx_sge[0].addr = addr;
+ priv->tx_sge[0].length = len;
+
++ priv->tx_wr.num_sge = 1;
+ priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
+
+ return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
+@@ -1030,13 +1032,13 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
+ struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+ int ret;
+
+- p->tx_ring = kzalloc(ipoib_sendq_size * sizeof *p->tx_ring,
+- GFP_KERNEL);
++ p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring);
+ if (!p->tx_ring) {
+ ipoib_warn(priv, "failed to allocate tx ring\n");
+ ret = -ENOMEM;
+ goto err_tx;
+ }
++ memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring);
+
+ p->qp = ipoib_cm_create_tx_qp(p->dev, p);
+ if (IS_ERR(p->qp)) {
+@@ -1077,6 +1079,7 @@ err_id:
+ ib_destroy_qp(p->qp);
+ err_qp:
+ p->qp = NULL;
++ vfree(p->tx_ring);
+ err_tx:
+ return ret;
+ }
+@@ -1127,7 +1130,7 @@ timeout:
+ if (p->qp)
+ ib_destroy_qp(p->qp);
+
+- kfree(p->tx_ring);
++ vfree(p->tx_ring);
+ kfree(p);
+ }
+
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+index f96477a..5728204 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -41,6 +41,7 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
++#include <linux/vmalloc.h>
+
+ #include <linux/if_arp.h> /* For ARPHRD_xxx */
+
+@@ -887,13 +888,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
+ goto out;
+ }
+
+- priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring,
+- GFP_KERNEL);
++ priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
+ if (!priv->tx_ring) {
+ printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
+ ca->name, ipoib_sendq_size);
+ goto out_rx_ring_cleanup;
+ }
++ memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring);
+
+ /* priv->tx_head, tx_tail & tx_outstanding are already 0 */
+
+@@ -903,7 +904,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
+ return 0;
+
+ out_tx_ring_cleanup:
+- kfree(priv->tx_ring);
++ vfree(priv->tx_ring);
+
+ out_rx_ring_cleanup:
+ kfree(priv->rx_ring);
+@@ -928,7 +929,7 @@ void ipoib_dev_cleanup(struct net_device *dev)
+ ipoib_ib_dev_cleanup(dev);
+
+ kfree(priv->rx_ring);
+- kfree(priv->tx_ring);
++ vfree(priv->tx_ring);
+
+ priv->rx_ring = NULL;
+ priv->tx_ring = NULL;
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+index 2628339..31a53c5 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+@@ -650,7 +650,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
+ */
+ spin_lock(&priv->lock);
+
+- if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) ||
++ if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) ||
+ !priv->broadcast ||
+ !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
+ ++dev->stats.tx_dropped;
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 714b8db..993f0a8 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -12311,6 +16834,142 @@
module_init(tifm_ms_init);
module_exit(tifm_ms_exit);
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 982e27b..962817e 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -108,6 +108,7 @@ config ACER_WMI
+ depends on ACPI
+ depends on LEDS_CLASS
+ depends on BACKLIGHT_CLASS_DEVICE
++ depends on SERIO_I8042
+ select ACPI_WMI
+ ---help---
+ This is a driver for newer Acer (and Wistron) laptops. It adds
+diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
+index 74d12b4..dd13a37 100644
+--- a/drivers/misc/acer-wmi.c
++++ b/drivers/misc/acer-wmi.c
+@@ -219,6 +219,15 @@ static struct dmi_system_id acer_quirks[] = {
+ },
+ {
+ .callback = dmi_matched,
++ .ident = "Acer Aspire 3610",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),
++ },
++ .driver_data = &quirk_acer_travelmate_2490,
++ },
++ {
++ .callback = dmi_matched,
+ .ident = "Acer Aspire 5100",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+@@ -228,6 +237,15 @@ static struct dmi_system_id acer_quirks[] = {
+ },
+ {
+ .callback = dmi_matched,
++ .ident = "Acer Aspire 5610",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
++ },
++ .driver_data = &quirk_acer_travelmate_2490,
++ },
++ {
++ .callback = dmi_matched,
+ .ident = "Acer Aspire 5630",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+@@ -761,11 +779,11 @@ enum led_brightness value)
+ }
+
+ static struct led_classdev mail_led = {
+- .name = "acer-mail:green",
++ .name = "acer-wmi::mail",
+ .brightness_set = mail_led_set,
+ };
+
+-static int __init acer_led_init(struct device *dev)
++static int __devinit acer_led_init(struct device *dev)
+ {
+ return led_classdev_register(dev, &mail_led);
+ }
+@@ -798,7 +816,7 @@ static struct backlight_ops acer_bl_ops = {
+ .update_status = update_bl_status,
+ };
+
+-static int __init acer_backlight_init(struct device *dev)
++static int __devinit acer_backlight_init(struct device *dev)
+ {
+ struct backlight_device *bd;
+
+@@ -817,7 +835,7 @@ static int __init acer_backlight_init(struct device *dev)
+ return 0;
+ }
+
+-static void __exit acer_backlight_exit(void)
++static void acer_backlight_exit(void)
+ {
+ backlight_device_unregister(acer_backlight_device);
+ }
+@@ -1052,11 +1070,12 @@ static int __init acer_wmi_init(void)
+
+ if (wmi_has_guid(WMID_GUID2) && interface) {
+ if (ACPI_FAILURE(WMID_set_capabilities())) {
+- printk(ACER_ERR "Unable to detect available devices\n");
++ printk(ACER_ERR "Unable to detect available WMID "
++ "devices\n");
+ return -ENODEV;
+ }
+ } else if (!wmi_has_guid(WMID_GUID2) && interface) {
+- printk(ACER_ERR "Unable to detect available devices\n");
++ printk(ACER_ERR "No WMID device detection method found\n");
+ return -ENODEV;
+ }
+
+@@ -1064,21 +1083,20 @@ static int __init acer_wmi_init(void)
+ interface = &AMW0_interface;
+
+ if (ACPI_FAILURE(AMW0_set_capabilities())) {
+- printk(ACER_ERR "Unable to detect available devices\n");
++ printk(ACER_ERR "Unable to detect available AMW0 "
++ "devices\n");
+ return -ENODEV;
+ }
+ }
+
+- if (wmi_has_guid(AMW0_GUID1)) {
+- if (ACPI_FAILURE(AMW0_find_mailled()))
+- printk(ACER_ERR "Unable to detect mail LED\n");
+- }
++ if (wmi_has_guid(AMW0_GUID1))
++ AMW0_find_mailled();
+
+ find_quirks();
+
+ if (!interface) {
+- printk(ACER_ERR "No or unsupported WMI interface, unable to ");
+- printk(KERN_CONT "load.\n");
++ printk(ACER_ERR "No or unsupported WMI interface, unable to "
++ "load\n");
+ return -ENODEV;
+ }
+
+diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
+index 899e3f7..02ff3d1 100644
+--- a/drivers/misc/sony-laptop.c
++++ b/drivers/misc/sony-laptop.c
+@@ -315,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event)
+ break;
+
+ default:
+- if (event > ARRAY_SIZE(sony_laptop_input_index)) {
++ if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
+ dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
+ break;
+ }
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 63a089b..67503ea 100644
--- a/drivers/misc/tifm_7xx1.c
@@ -12998,6 +17657,30 @@
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
/* Gigabyte */
+diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
+index 6a9403d..d708358 100644
+--- a/drivers/pci/bus.c
++++ b/drivers/pci/bus.c
+@@ -143,14 +143,18 @@ void pci_bus_add_devices(struct pci_bus *bus)
+ /* register the bus with sysfs as the parent is now
+ * properly registered. */
+ child_bus = dev->subordinate;
++ if (child_bus->is_added)
++ continue;
+ child_bus->dev.parent = child_bus->bridge;
+ retval = device_register(&child_bus->dev);
+ if (retval)
+ dev_err(&dev->dev, "Error registering pci_bus,"
+ " continuing...\n");
+- else
++ else {
++ child_bus->is_added = 1;
+ retval = device_create_file(&child_bus->dev,
+ &dev_attr_cpuaffinity);
++ }
+ if (retval)
+ dev_err(&dev->dev, "Error creating cpuaffinity"
+ " file, continuing...\n");
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 600ed7b..bbccde9 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
@@ -13010,6 +17693,48 @@
rc = -ENODEV;
goto error;
}
+diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
+index 4a23654..72f7476 100644
+--- a/drivers/pci/pci-acpi.c
++++ b/drivers/pci/pci-acpi.c
+@@ -272,21 +272,29 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
+ acpi_handle tmp;
+- static int state_conv[] = {
+- [0] = 0,
+- [1] = 1,
+- [2] = 2,
+- [3] = 3,
+- [4] = 3
++ static const u8 state_conv[] = {
++ [PCI_D0] = ACPI_STATE_D0,
++ [PCI_D1] = ACPI_STATE_D1,
++ [PCI_D2] = ACPI_STATE_D2,
++ [PCI_D3hot] = ACPI_STATE_D3,
++ [PCI_D3cold] = ACPI_STATE_D3
+ };
+- int acpi_state = state_conv[(int __force) state];
+
+ if (!handle)
+ return -ENODEV;
+ /* If the ACPI device has _EJ0, ignore the device */
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+ return 0;
+- return acpi_bus_set_power(handle, acpi_state);
++
++ switch (state) {
++ case PCI_D0:
++ case PCI_D1:
++ case PCI_D2:
++ case PCI_D3hot:
++ case PCI_D3cold:
++ return acpi_bus_set_power(handle, state_conv[state]);
++ }
++ return -EINVAL;
+ }
+
+
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 4065139..3799320 100644
--- a/drivers/pnp/quirks.c
@@ -13152,6 +17877,330 @@
.owner = THIS_MODULE,
.name = "of_serial",
.probe = of_platform_serial_probe,
+diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
+index c47a650..41a3d00 100644
+--- a/drivers/spi/au1550_spi.c
++++ b/drivers/spi/au1550_spi.c
+@@ -99,7 +99,7 @@ static dbdev_tab_t au1550_spi_mem_dbdev =
+ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
+
+
+-/**
++/*
+ * compute BRG and DIV bits to setup spi clock based on main input clock rate
+ * that was specified in platform data structure
+ * according to au1550 datasheet:
+@@ -650,7 +650,7 @@ static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+ return hw->txrx_bufs(spi, t);
+ }
+
+-static irqreturn_t au1550_spi_irq(int irq, void *dev, struct pt_regs *regs)
++static irqreturn_t au1550_spi_irq(int irq, void *dev)
+ {
+ struct au1550_spi *hw = dev;
+ return hw->irq_callback(hw);
+diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
+index f7f8580..71e8814 100644
+--- a/drivers/spi/spi_bitbang.c
++++ b/drivers/spi/spi_bitbang.c
+@@ -344,12 +344,14 @@ static void bitbang_work(struct work_struct *work)
+ t->rx_dma = t->tx_dma = 0;
+ status = bitbang->txrx_bufs(spi, t);
+ }
++ if (status > 0)
++ m->actual_length += status;
+ if (status != t->len) {
+- if (status > 0)
+- status = -EMSGSIZE;
++ /* always report some kind of error */
++ if (status >= 0)
++ status = -EREMOTEIO;
+ break;
+ }
+- m->actual_length += status;
+ status = 0;
+
+ /* protocol tweaks before next transfer */
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index 69f19f2..3ab313e 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -4,6 +4,7 @@
+
+ menuconfig THERMAL
+ bool "Generic Thermal sysfs driver"
++ select HWMON
+ default y
+ help
+ Generic Thermal Sysfs driver offers a generic mechanism for
+diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c
+index 8b86e53..41bd4c8 100644
+--- a/drivers/thermal/thermal.c
++++ b/drivers/thermal/thermal.c
+@@ -30,8 +30,10 @@
+ #include <linux/idr.h>
+ #include <linux/thermal.h>
+ #include <linux/spinlock.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
+
+-MODULE_AUTHOR("Zhang Rui")
++MODULE_AUTHOR("Zhang Rui");
+ MODULE_DESCRIPTION("Generic thermal management sysfs support");
+ MODULE_LICENSE("GPL");
+
+@@ -56,6 +58,9 @@ static LIST_HEAD(thermal_tz_list);
+ static LIST_HEAD(thermal_cdev_list);
+ static DEFINE_MUTEX(thermal_list_lock);
+
++static struct device *thermal_hwmon;
++#define MAX_THERMAL_ZONES 10
++
+ static int get_idr(struct idr *idr, struct mutex *lock, int *id)
+ {
+ int err;
+@@ -87,7 +92,67 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
+ mutex_unlock(lock);
+ }
+
+-/* sys I/F for thermal zone */
++/* hwmon sys I/F*/
++static ssize_t
++name_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "thermal_sys_class\n");
++}
++
++static ssize_t
++temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct thermal_zone_device *tz;
++ struct sensor_device_attribute *sensor_attr
++ = to_sensor_dev_attr(attr);
++
++ list_for_each_entry(tz, &thermal_tz_list, node)
++ if (tz->id == sensor_attr->index)
++ return tz->ops->get_temp(tz, buf);
++
++ return -ENODEV;
++}
++
++static ssize_t
++temp_crit_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct thermal_zone_device *tz;
++ struct sensor_device_attribute *sensor_attr
++ = to_sensor_dev_attr(attr);
++
++ list_for_each_entry(tz, &thermal_tz_list, node)
++ if (tz->id == sensor_attr->index)
++ return tz->ops->get_trip_temp(tz, 0, buf);
++
++ return -ENODEV;
++}
++
++static DEVICE_ATTR(name, 0444, name_show, NULL);
++static struct sensor_device_attribute sensor_attrs[] = {
++ SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0),
++ SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0),
++ SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1),
++ SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1),
++ SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2),
++ SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2),
++ SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3),
++ SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3),
++ SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4),
++ SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4),
++ SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5),
++ SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5),
++ SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6),
++ SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6),
++ SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7),
++ SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7),
++ SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8),
++ SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8),
++ SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9),
++ SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9),
++};
++
++/* thermal zone sys I/F */
+
+ #define to_thermal_zone(_dev) \
+ container_of(_dev, struct thermal_zone_device, device)
+@@ -214,7 +279,7 @@ do { \
+ device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
+ } while (0)
+
+-/* sys I/F for cooling device */
++/* cooling device sys I/F */
+ #define to_cooling_device(_dev) \
+ container_of(_dev, struct thermal_cooling_device, device)
+
+@@ -447,6 +512,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
+ struct thermal_zone_device *pos;
+ int result;
+
++ if (!type)
++ return ERR_PTR(-EINVAL);
++
+ if (strlen(type) >= THERMAL_NAME_LENGTH)
+ return ERR_PTR(-EINVAL);
+
+@@ -477,11 +545,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
+ }
+
+ /* sys I/F */
+- if (type) {
+- result = device_create_file(&cdev->device, &dev_attr_cdev_type);
+- if (result)
+- goto unregister;
+- }
++ result = device_create_file(&cdev->device, &dev_attr_cdev_type);
++ if (result)
++ goto unregister;
+
+ result = device_create_file(&cdev->device, &dev_attr_max_state);
+ if (result)
+@@ -547,8 +613,8 @@ void thermal_cooling_device_unregister(struct
+ tz->ops->unbind(tz, cdev);
+ }
+ mutex_unlock(&thermal_list_lock);
+- if (cdev->type[0])
+- device_remove_file(&cdev->device, &dev_attr_cdev_type);
++
++ device_remove_file(&cdev->device, &dev_attr_cdev_type);
+ device_remove_file(&cdev->device, &dev_attr_max_state);
+ device_remove_file(&cdev->device, &dev_attr_cur_state);
+
+@@ -580,6 +646,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ int result;
+ int count;
+
++ if (!type)
++ return ERR_PTR(-EINVAL);
++
+ if (strlen(type) >= THERMAL_NAME_LENGTH)
+ return ERR_PTR(-EINVAL);
+
+@@ -601,6 +670,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ kfree(tz);
+ return ERR_PTR(result);
+ }
++ if (tz->id >= MAX_THERMAL_ZONES) {
++ printk(KERN_ERR PREFIX
++ "Too many thermal zones\n");
++ release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
++ kfree(tz);
++ return ERR_PTR(-EINVAL);
++ }
+
+ strcpy(tz->type, type);
+ tz->ops = ops;
+@@ -615,13 +691,28 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ return ERR_PTR(result);
+ }
+
+- /* sys I/F */
+- if (type) {
+- result = device_create_file(&tz->device, &dev_attr_type);
+- if (result)
+- goto unregister;
++ /* hwmon sys I/F */
++ result = device_create_file(thermal_hwmon,
++ &sensor_attrs[tz->id * 2].dev_attr);
++ if (result)
++ goto unregister;
++
++ if (trips > 0) {
++ char buf[40];
++ result = tz->ops->get_trip_type(tz, 0, buf);
++ if (result > 0 && !strcmp(buf, "critical\n")) {
++ result = device_create_file(thermal_hwmon,
++ &sensor_attrs[tz->id * 2 + 1].dev_attr);
++ if (result)
++ goto unregister;
++ }
+ }
+
++ /* sys I/F */
++ result = device_create_file(&tz->device, &dev_attr_type);
++ if (result)
++ goto unregister;
++
+ result = device_create_file(&tz->device, &dev_attr_temp);
+ if (result)
+ goto unregister;
+@@ -687,8 +778,17 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+ tz->ops->unbind(tz, cdev);
+ mutex_unlock(&thermal_list_lock);
+
+- if (tz->type[0])
+- device_remove_file(&tz->device, &dev_attr_type);
++ device_remove_file(thermal_hwmon,
++ &sensor_attrs[tz->id * 2].dev_attr);
++ if (tz->trips > 0) {
++ char buf[40];
++ if (tz->ops->get_trip_type(tz, 0, buf) > 0)
++ if (!strcmp(buf, "critical\n"))
++ device_remove_file(thermal_hwmon,
++ &sensor_attrs[tz->id * 2 + 1].dev_attr);
++ }
++
++ device_remove_file(&tz->device, &dev_attr_type);
+ device_remove_file(&tz->device, &dev_attr_temp);
+ if (tz->ops->get_mode)
+ device_remove_file(&tz->device, &dev_attr_mode);
+@@ -705,6 +805,19 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+
+ EXPORT_SYMBOL(thermal_zone_device_unregister);
+
++static void thermal_exit(void)
++{
++ if (thermal_hwmon) {
++ device_remove_file(thermal_hwmon, &dev_attr_name);
++ hwmon_device_unregister(thermal_hwmon);
++ }
++ class_unregister(&thermal_class);
++ idr_destroy(&thermal_tz_idr);
++ idr_destroy(&thermal_cdev_idr);
++ mutex_destroy(&thermal_idr_lock);
++ mutex_destroy(&thermal_list_lock);
++}
++
+ static int __init thermal_init(void)
+ {
+ int result = 0;
+@@ -716,16 +829,20 @@ static int __init thermal_init(void)
+ mutex_destroy(&thermal_idr_lock);
+ mutex_destroy(&thermal_list_lock);
+ }
+- return result;
+-}
+
+-static void __exit thermal_exit(void)
+-{
+- class_unregister(&thermal_class);
+- idr_destroy(&thermal_tz_idr);
+- idr_destroy(&thermal_cdev_idr);
+- mutex_destroy(&thermal_idr_lock);
+- mutex_destroy(&thermal_list_lock);
++ thermal_hwmon = hwmon_device_register(NULL);
++ if (IS_ERR(thermal_hwmon)) {
++ result = PTR_ERR(thermal_hwmon);
++ thermal_hwmon = NULL;
++ printk(KERN_ERR PREFIX
++ "unable to register hwmon device\n");
++ thermal_exit();
++ return result;
++ }
++
++ result = device_create_file(thermal_hwmon, &dev_attr_name);
++
++ return result;
+ }
+
+ subsys_initcall(thermal_init);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c139551..6f45dd6 100644
--- a/drivers/usb/gadget/Kconfig
@@ -15751,6 +20800,72 @@
return register_pernet_subsys(&proc_net_ns_ops);
}
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 6dc0334..4206454 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -640,17 +640,17 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+
+ ret = -EACCES;
+ if (!ptrace_may_attach(task))
+- goto out;
++ goto out_task;
+
+ ret = -EINVAL;
+ /* file position must be aligned */
+ if (*ppos % PM_ENTRY_BYTES)
+- goto out;
++ goto out_task;
+
+ ret = 0;
+ mm = get_task_mm(task);
+ if (!mm)
+- goto out;
++ goto out_task;
+
+ ret = -ENOMEM;
+ uaddr = (unsigned long)buf & PAGE_MASK;
+@@ -658,7 +658,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
+ pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+- goto out_task;
++ goto out_mm;
+
+ down_read(¤t->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, uaddr, pagecount,
+@@ -668,6 +668,12 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ if (ret < 0)
+ goto out_free;
+
++ if (ret != pagecount) {
++ pagecount = ret;
++ ret = -EFAULT;
++ goto out_pages;
++ }
++
+ pm.out = buf;
+ pm.end = buf + count;
+
+@@ -699,15 +705,17 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ ret = pm.out - buf;
+ }
+
++out_pages:
+ for (; pagecount; pagecount--) {
+ page = pages[pagecount-1];
+ if (!PageReserved(page))
+ SetPageDirty(page);
+ page_cache_release(page);
+ }
+- mmput(mm);
+ out_free:
+ kfree(pages);
++out_mm:
++ mmput(mm);
+ out_task:
+ put_task_struct(task);
+ out:
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 1c2b55c..0f64044 100644
--- a/include/asm-arm/arch-omap/board-h3.h
@@ -15859,6 +20974,37 @@
#endif
#include <asm/memory.h>
+diff --git a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h
+index a22350e..356068c 100644
+--- a/include/asm-h8300/uaccess.h
++++ b/include/asm-h8300/uaccess.h
+@@ -91,22 +91,19 @@ extern int __put_user_bad(void);
+ #define get_user(x, ptr) \
+ ({ \
+ int __gu_err = 0; \
+- uint32_t __gu_val = 0; \
++ typeof(*(ptr)) __gu_val = *ptr; \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ case 2: \
+ case 4: \
+- __gu_val = *(ptr); \
+- break; \
+- case 8: \
+- memcpy(&__gu_val, ptr, sizeof (*(ptr))); \
++ case 8: \
+ break; \
+ default: \
+- __gu_val = 0; \
+ __gu_err = __get_user_bad(); \
++ __gu_val = 0; \
+ break; \
+ } \
+- (x) = (typeof(*(ptr)))__gu_val; \
++ (x) = __gu_val; \
+ __gu_err; \
+ })
+ #define __get_user(x, ptr) get_user(x, ptr)
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index 4933b49..01e7ead 100644
--- a/include/asm-mips/cacheflush.h
@@ -16415,10 +21561,18 @@
/* nfnetlink groups: Up to 32 maximum */
diff --git a/include/linux/pci.h b/include/linux/pci.h
-index f3165e7..38eff19 100644
+index f3165e7..9010f54 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
-@@ -389,13 +389,13 @@ struct pci_driver {
+@@ -278,6 +278,7 @@ struct pci_bus {
+ struct device dev;
+ struct bin_attribute *legacy_io; /* legacy I/O for this bus */
+ struct bin_attribute *legacy_mem; /* legacy mem */
++ unsigned int is_added:1;
+ };
+
+ #define pci_bus_b(n) list_entry(n, struct pci_bus, node)
+@@ -389,13 +390,13 @@ struct pci_driver {
#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
/**
@@ -16730,6 +21884,115 @@
return 0;
}
+diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
+index 7983317..6233f3b 100644
+--- a/kernel/power/Kconfig
++++ b/kernel/power/Kconfig
+@@ -190,7 +190,7 @@ config APM_EMULATION
+ notification of APM "events" (e.g. battery status change).
+
+ In order to use APM, you will need supporting software. For location
+- and more information, read <file:Documentation/pm.txt> and the
++ and more information, read <file:Documentation/power/pm.txt> and the
+ Battery Powered Linux mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index 72a020c..5f91a07 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
+ * of @bm->cur_zone_bm are updated.
+ */
+
+-static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
++static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
+ void **addr, unsigned int *bit_nr)
+ {
+ struct zone_bitmap *zone_bm;
+@@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
+ while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) {
+ zone_bm = zone_bm->next;
+
+- BUG_ON(!zone_bm);
++ if (!zone_bm)
++ return -EFAULT;
+ }
+ bm->cur.zone_bm = zone_bm;
+ }
+@@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
+ pfn -= bb->start_pfn;
+ *bit_nr = pfn % BM_BITS_PER_CHUNK;
+ *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
++ return 0;
+ }
+
+ static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
+ {
+ void *addr;
+ unsigned int bit;
++ int error;
+
+- memory_bm_find_bit(bm, pfn, &addr, &bit);
++ error = memory_bm_find_bit(bm, pfn, &addr, &bit);
++ BUG_ON(error);
+ set_bit(bit, addr);
+ }
+
++static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn)
++{
++ void *addr;
++ unsigned int bit;
++ int error;
++
++ error = memory_bm_find_bit(bm, pfn, &addr, &bit);
++ if (!error)
++ set_bit(bit, addr);
++ return error;
++}
++
+ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
+ {
+ void *addr;
+ unsigned int bit;
++ int error;
+
+- memory_bm_find_bit(bm, pfn, &addr, &bit);
++ error = memory_bm_find_bit(bm, pfn, &addr, &bit);
++ BUG_ON(error);
+ clear_bit(bit, addr);
+ }
+
+@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
+ {
+ void *addr;
+ unsigned int bit;
++ int error;
+
+- memory_bm_find_bit(bm, pfn, &addr, &bit);
++ error = memory_bm_find_bit(bm, pfn, &addr, &bit);
++ BUG_ON(error);
+ return test_bit(bit, addr);
+ }
+
+@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
+ region->end_pfn << PAGE_SHIFT);
+
+ for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
+- if (pfn_valid(pfn))
+- memory_bm_set_bit(bm, pfn);
++ if (pfn_valid(pfn)) {
++ /*
++ * It is safe to ignore the result of
++ * mem_bm_set_bit_check() here, since we won't
++ * touch the PFNs for which the error is
++ * returned anyway.
++ */
++ mem_bm_set_bit_check(bm, pfn);
++ }
+ }
+ }
+
diff --git a/kernel/sched.c b/kernel/sched.c
index b02e4fc..1cb53fb 100644
--- a/kernel/sched.c
@@ -16783,6 +22046,66 @@
for (class = sched_class_highest; class; class = class->next) {
if (class->join_domain)
+diff --git a/lib/swiotlb.c b/lib/swiotlb.c
+index 4bb5a11..0259228 100644
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -310,7 +310,9 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ start_dma_addr = virt_to_bus(io_tlb_start) & mask;
+
+ offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+- max_slots = ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
++ max_slots = mask + 1
++ ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
++ : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+
+ /*
+ * For mappings greater than a page, we limit the stride (and
+@@ -333,16 +335,18 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ index = ALIGN(io_tlb_index, stride);
+ if (index >= io_tlb_nslabs)
+ index = 0;
+-
+- while (is_span_boundary(index, nslots, offset_slots,
+- max_slots)) {
+- index += stride;
+- if (index >= io_tlb_nslabs)
+- index = 0;
+- }
+ wrap = index;
+
+ do {
++ while (is_span_boundary(index, nslots, offset_slots,
++ max_slots)) {
++ index += stride;
++ if (index >= io_tlb_nslabs)
++ index = 0;
++ if (index == wrap)
++ goto not_found;
++ }
++
+ /*
+ * If we find a slot that indicates we have 'nslots'
+ * number of contiguous buffers, we allocate the
+@@ -367,14 +371,12 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+
+ goto found;
+ }
+- do {
+- index += stride;
+- if (index >= io_tlb_nslabs)
+- index = 0;
+- } while (is_span_boundary(index, nslots, offset_slots,
+- max_slots));
++ index += stride;
++ if (index >= io_tlb_nslabs)
++ index = 0;
+ } while (index != wrap);
+
++ not_found:
+ spin_unlock_irqrestore(&io_tlb_lock, flags);
+ return NULL;
+ }
diff --git a/mm/filemap.c b/mm/filemap.c
index ab98557..df343d1 100644
--- a/mm/filemap.c
@@ -17648,6 +22971,114 @@
}
static int svc_rdma_has_wspace(struct svc_xprt *xprt)
+diff --git a/scripts/kernel-doc b/scripts/kernel-doc
+index 74c2f9d..263d04a 100755
+--- a/scripts/kernel-doc
++++ b/scripts/kernel-doc
+@@ -247,6 +247,10 @@ my ($function, %function_table,%parametertypes,$declaration_purpose);
+ my ($type,$declaration_name,$return_type);
+ my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
+
++if (defined($ENV{'KBUILD_VERBOSE'})) {
++ $verbose = "$ENV{'KBUILD_VERBOSE'}";
++}
++
+ # Generated docbook code is inserted in a template at a point where
+ # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
+ # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
+diff --git a/security/smack/smack.h b/security/smack/smack.h
+index a21a0e9..62c1e98 100644
+--- a/security/smack/smack.h
++++ b/security/smack/smack.h
+@@ -26,14 +26,6 @@
+ #define SMK_MAXLEN 23
+ #define SMK_LABELLEN (SMK_MAXLEN+1)
+
+-/*
+- * How many kinds of access are there?
+- * Here's your answer.
+- */
+-#define SMK_ACCESSDASH '-'
+-#define SMK_ACCESSLOW "rwxa"
+-#define SMK_ACCESSKINDS (sizeof(SMK_ACCESSLOW) - 1)
+-
+ struct superblock_smack {
+ char *smk_root;
+ char *smk_floor;
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+index 358c92c..afe7c9b 100644
+--- a/security/smack/smackfs.c
++++ b/security/smack/smackfs.c
+@@ -81,10 +81,23 @@ static struct semaphore smack_write_sem;
+ /*
+ * Values for parsing cipso rules
+ * SMK_DIGITLEN: Length of a digit field in a rule.
+- * SMK_CIPSOMEN: Minimum possible cipso rule length.
++ * SMK_CIPSOMIN: Minimum possible cipso rule length.
++ * SMK_CIPSOMAX: Maximum possible cipso rule length.
+ */
+ #define SMK_DIGITLEN 4
+-#define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN)
++#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
++#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
++
++/*
++ * Values for parsing MAC rules
++ * SMK_ACCESS: Maximum possible combination of access permissions
++ * SMK_ACCESSLEN: Maximum length for a rule access field
++ * SMK_LOADLEN: Smack rule length
++ */
++#define SMK_ACCESS "rwxa"
++#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
++#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
++
+
+ /*
+ * Seq_file read operations for /smack/load
+@@ -229,14 +242,10 @@ static void smk_set_access(struct smack_rule *srp)
+ * The format is exactly:
+ * char subject[SMK_LABELLEN]
+ * char object[SMK_LABELLEN]
+- * char access[SMK_ACCESSKINDS]
+- *
+- * Anything following is commentary and ignored.
++ * char access[SMK_ACCESSLEN]
+ *
+- * writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes.
++ * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
+ */
+-#define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS)
+-
+ static ssize_t smk_write_load(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -253,7 +262,7 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
+ return -EPERM;
+ if (*ppos != 0)
+ return -EINVAL;
+- if (count < MINIMUM_LOAD)
++ if (count != SMK_LOADLEN)
+ return -EINVAL;
+
+ data = kzalloc(count, GFP_KERNEL);
+@@ -513,7 +522,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
+ return -EPERM;
+ if (*ppos != 0)
+ return -EINVAL;
+- if (count <= SMK_CIPSOMIN)
++ if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
+ return -EINVAL;
+
+ data = kzalloc(count + 1, GFP_KERNEL);
+@@ -547,7 +556,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
+ if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
+ goto out;
+
+- if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
++ if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
+ goto out;
+
+ memset(mapcatset, 0, sizeof(mapcatset));
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 675672f..f48838a 100644
--- a/sound/usb/usbaudio.c
Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 Fri Mar 14 10:05:47 2008
@@ -1,4 +1,4 @@
-+ bugfix/all/patch-2.6.25-rc5-git3
++ bugfix/all/patch-2.6.25-rc5-git4
+ debian/version.patch
+ debian/kernelvariables.patch
+ debian/doc-build-parallel.patch
More information about the Kernel-svn-changes
mailing list