[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(&current->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